blob: b052454a783e83c855b35e57c02f14dfcc04041b [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"
24#include "common/utilities.h"
25
26namespace gl
27{
28
Jamie Madillc29968b2016-01-20 11:17:23 -050029namespace
30{
31
32bool IsPartialBlit(gl::Context *context,
33 const FramebufferAttachment *readBuffer,
34 const FramebufferAttachment *writeBuffer,
35 GLint srcX0,
36 GLint srcY0,
37 GLint srcX1,
38 GLint srcY1,
39 GLint dstX0,
40 GLint dstY0,
41 GLint dstX1,
42 GLint dstY1)
43{
44 const Extents &writeSize = writeBuffer->getSize();
45 const Extents &readSize = readBuffer->getSize();
46
47 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
48 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
49 {
50 return true;
51 }
52
Jamie Madilldfde6ab2016-06-09 07:07:18 -070053 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050054 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050056 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
57 scissor.height < writeSize.height;
58 }
59
60 return false;
61}
62
Sami Väisänend59ca052016-06-21 16:10:00 +030063template <typename T>
64bool ValidatePathInstances(gl::Context *context,
65 GLsizei numPaths,
66 const void *paths,
67 GLuint pathBase)
68{
69 const auto *array = static_cast<const T *>(paths);
70
71 for (GLsizei i = 0; i < numPaths; ++i)
72 {
73 const GLuint pathName = array[i] + pathBase;
74 if (context->hasPath(pathName) && !context->hasPathData(pathName))
75 {
76 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
77 return false;
78 }
79 }
80 return true;
81}
82
83bool ValidateInstancedPathParameters(gl::Context *context,
84 GLsizei numPaths,
85 GLenum pathNameType,
86 const void *paths,
87 GLuint pathBase,
88 GLenum transformType,
89 const GLfloat *transformValues)
90{
91 if (!context->getExtensions().pathRendering)
92 {
93 context->handleError(
94 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
95 return false;
96 }
97
98 if (paths == nullptr)
99 {
100 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
101 return false;
102 }
103
104 if (numPaths < 0)
105 {
106 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
107 return false;
108 }
109
110 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
111 {
112 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
113 return false;
114 }
115
116 std::uint32_t pathNameTypeSize = 0;
117 std::uint32_t componentCount = 0;
118
119 switch (pathNameType)
120 {
121 case GL_UNSIGNED_BYTE:
122 pathNameTypeSize = sizeof(GLubyte);
123 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
124 return false;
125 break;
126
127 case GL_BYTE:
128 pathNameTypeSize = sizeof(GLbyte);
129 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
130 return false;
131 break;
132
133 case GL_UNSIGNED_SHORT:
134 pathNameTypeSize = sizeof(GLushort);
135 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
136 return false;
137 break;
138
139 case GL_SHORT:
140 pathNameTypeSize = sizeof(GLshort);
141 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
142 return false;
143 break;
144
145 case GL_UNSIGNED_INT:
146 pathNameTypeSize = sizeof(GLuint);
147 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
148 return false;
149 break;
150
151 case GL_INT:
152 pathNameTypeSize = sizeof(GLint);
153 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
154 return false;
155 break;
156
157 default:
158 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
159 return false;
160 }
161
162 switch (transformType)
163 {
164 case GL_NONE:
165 componentCount = 0;
166 break;
167 case GL_TRANSLATE_X_CHROMIUM:
168 case GL_TRANSLATE_Y_CHROMIUM:
169 componentCount = 1;
170 break;
171 case GL_TRANSLATE_2D_CHROMIUM:
172 componentCount = 2;
173 break;
174 case GL_TRANSLATE_3D_CHROMIUM:
175 componentCount = 3;
176 break;
177 case GL_AFFINE_2D_CHROMIUM:
178 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
179 componentCount = 6;
180 break;
181 case GL_AFFINE_3D_CHROMIUM:
182 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
183 componentCount = 12;
184 break;
185 default:
186 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
187 return false;
188 }
189 if (componentCount != 0 && transformValues == nullptr)
190 {
191 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
192 return false;
193 }
194
195 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
196 checkedSize += (numPaths * pathNameTypeSize);
197 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
198 if (!checkedSize.IsValid())
199 {
200 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
201 return false;
202 }
203
204 return true;
205}
206
Jamie Madillc29968b2016-01-20 11:17:23 -0500207} // anonymous namespace
208
Geoff Langb1196682014-07-23 13:47:29 -0400209bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400210 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
211 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
212{
Jamie Madill6f38f822014-06-06 17:12:20 -0400213 if (!ValidTexture2DDestinationTarget(context, target))
214 {
Jamie Madill437fa652016-05-03 15:13:24 -0400215 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400216 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400217 }
218
Austin Kinross08528e12015-10-07 16:24:40 -0700219 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 {
Jamie Madill437fa652016-05-03 15:13:24 -0400221 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 }
224
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 if (level < 0 || xoffset < 0 ||
226 std::numeric_limits<GLsizei>::max() - xoffset < width ||
227 std::numeric_limits<GLsizei>::max() - yoffset < height)
228 {
Jamie Madill437fa652016-05-03 15:13:24 -0400229 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400231 }
232
Geoff Lang005df412013-10-16 14:12:50 -0400233 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400234 {
Jamie Madill437fa652016-05-03 15:13:24 -0400235 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400236 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400237 }
238
Geoff Langaae65a42014-05-26 12:43:44 -0400239 const gl::Caps &caps = context->getCaps();
240
Geoff Langa9be0dc2014-12-17 12:34:40 -0500241 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400242 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500243 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
244 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400245 {
Jamie Madill437fa652016-05-03 15:13:24 -0400246 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400248 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500249 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500250 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500251 {
252 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253 {
Jamie Madill437fa652016-05-03 15:13:24 -0400254 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400256 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400257
Geoff Langa9be0dc2014-12-17 12:34:40 -0500258 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
259 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
260 {
Jamie Madill437fa652016-05-03 15:13:24 -0400261 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500262 return false;
263 }
264 }
265 else
266 {
Jamie Madill437fa652016-05-03 15:13:24 -0400267 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400268 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400269 }
270
Geoff Lang691e58c2014-12-19 17:03:25 -0500271 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400272 if (!texture)
273 {
Jamie Madill437fa652016-05-03 15:13:24 -0400274 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400275 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400276 }
277
Geoff Langa9be0dc2014-12-17 12:34:40 -0500278 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400279 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500280 if (format != GL_NONE)
281 {
Geoff Lang051dbc72015-01-05 15:48:58 -0500282 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500283 {
Jamie Madill437fa652016-05-03 15:13:24 -0400284 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500285 return false;
286 }
287 }
288
289 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
290 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
291 {
Jamie Madill437fa652016-05-03 15:13:24 -0400292 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500293 return false;
294 }
295 }
296 else
297 {
Geoff Lang69cce582015-09-17 13:20:36 -0400298 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500299 {
Jamie Madill437fa652016-05-03 15:13:24 -0400300 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500301 return false;
302 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400303 }
304
305 // Verify zero border
306 if (border != 0)
307 {
Jamie Madill437fa652016-05-03 15:13:24 -0400308 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400309 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400310 }
311
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 if (isCompressed)
313 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400314 GLenum actualInternalFormat =
315 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 switch (actualInternalFormat)
317 {
318 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
319 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400320 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400321 {
Jamie Madill437fa652016-05-03 15:13:24 -0400322 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400323 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400324 }
325 break;
326 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400327 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 {
Jamie Madill437fa652016-05-03 15:13:24 -0400329 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400330 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331 }
332 break;
333 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400334 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 {
Jamie Madill437fa652016-05-03 15:13:24 -0400336 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400338 }
339 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400340 case GL_ETC1_RGB8_OES:
341 if (!context->getExtensions().compressedETC1RGB8Texture)
342 {
Jamie Madill437fa652016-05-03 15:13:24 -0400343 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400344 return false;
345 }
346 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800347 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
348 if (!context->getExtensions().lossyETCDecode)
349 {
Jamie Madill437fa652016-05-03 15:13:24 -0400350 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800351 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
352 return false;
353 }
354 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400355 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400356 context->handleError(Error(
tmartino0ccd5ae2015-10-01 14:33:14 -0400357 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
358 return false;
359 }
360 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
361 {
Jamie Madill437fa652016-05-03 15:13:24 -0400362 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 }
365 }
366 else
367 {
368 // validate <type> by itself (used as secondary key below)
369 switch (type)
370 {
371 case GL_UNSIGNED_BYTE:
372 case GL_UNSIGNED_SHORT_5_6_5:
373 case GL_UNSIGNED_SHORT_4_4_4_4:
374 case GL_UNSIGNED_SHORT_5_5_5_1:
375 case GL_UNSIGNED_SHORT:
376 case GL_UNSIGNED_INT:
377 case GL_UNSIGNED_INT_24_8_OES:
378 case GL_HALF_FLOAT_OES:
379 case GL_FLOAT:
380 break;
381 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400382 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 }
385
386 // validate <format> + <type> combinations
387 // - invalid <format> -> sets INVALID_ENUM
388 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
389 switch (format)
390 {
391 case GL_ALPHA:
392 case GL_LUMINANCE:
393 case GL_LUMINANCE_ALPHA:
394 switch (type)
395 {
396 case GL_UNSIGNED_BYTE:
397 case GL_FLOAT:
398 case GL_HALF_FLOAT_OES:
399 break;
Geoff Langb1196682014-07-23 13:47:29 -0400400 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400401 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400403 }
404 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400405 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400406 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400407 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400408 {
Jamie Madill437fa652016-05-03 15:13:24 -0400409 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400410 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400411 }
412 switch (type)
413 {
414 case GL_UNSIGNED_BYTE:
415 case GL_FLOAT:
416 case GL_HALF_FLOAT_OES:
417 break;
418 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400419 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400420 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400421 }
422 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 case GL_RGB:
424 switch (type)
425 {
426 case GL_UNSIGNED_BYTE:
427 case GL_UNSIGNED_SHORT_5_6_5:
428 case GL_FLOAT:
429 case GL_HALF_FLOAT_OES:
430 break;
431 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400432 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400433 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400434 }
435 break;
436 case GL_RGBA:
437 switch (type)
438 {
439 case GL_UNSIGNED_BYTE:
440 case GL_UNSIGNED_SHORT_4_4_4_4:
441 case GL_UNSIGNED_SHORT_5_5_5_1:
442 case GL_FLOAT:
443 case GL_HALF_FLOAT_OES:
444 break;
445 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400448 }
449 break;
450 case GL_BGRA_EXT:
451 switch (type)
452 {
453 case GL_UNSIGNED_BYTE:
454 break;
455 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400456 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400457 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400458 }
459 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400460 case GL_SRGB_EXT:
461 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400462 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400463 {
Jamie Madill437fa652016-05-03 15:13:24 -0400464 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400465 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400466 }
467 switch (type)
468 {
469 case GL_UNSIGNED_BYTE:
470 break;
471 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400472 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400473 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400474 }
475 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
477 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
478 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
479 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
480 break;
481 case GL_DEPTH_COMPONENT:
482 switch (type)
483 {
484 case GL_UNSIGNED_SHORT:
485 case GL_UNSIGNED_INT:
486 break;
487 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400488 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400489 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400490 }
491 break;
492 case GL_DEPTH_STENCIL_OES:
493 switch (type)
494 {
495 case GL_UNSIGNED_INT_24_8_OES:
496 break;
497 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400498 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400499 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400500 }
501 break;
502 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400503 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400505 }
506
507 switch (format)
508 {
509 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
510 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400511 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400512 {
Jamie Madill437fa652016-05-03 15:13:24 -0400513 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400515 }
516 else
517 {
Jamie Madill437fa652016-05-03 15:13:24 -0400518 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400519 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400520 }
521 break;
522 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400523 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400524 {
Jamie Madill437fa652016-05-03 15:13:24 -0400525 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400526 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400527 }
528 else
529 {
Jamie Madill437fa652016-05-03 15:13:24 -0400530 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400531 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400532 }
533 break;
534 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400535 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400536 {
Jamie Madill437fa652016-05-03 15:13:24 -0400537 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400538 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400539 }
540 else
541 {
Jamie Madill437fa652016-05-03 15:13:24 -0400542 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400543 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400544 }
545 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400546 case GL_ETC1_RGB8_OES:
547 if (context->getExtensions().compressedETC1RGB8Texture)
548 {
Jamie Madill437fa652016-05-03 15:13:24 -0400549 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400550 return false;
551 }
552 else
553 {
Jamie Madill437fa652016-05-03 15:13:24 -0400554 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400555 return false;
556 }
557 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800558 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
559 if (context->getExtensions().lossyETCDecode)
560 {
Jamie Madill437fa652016-05-03 15:13:24 -0400561 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800562 Error(GL_INVALID_OPERATION,
563 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
564 return false;
565 }
566 else
567 {
Jamie Madill437fa652016-05-03 15:13:24 -0400568 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800569 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
570 return false;
571 }
572 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400573 case GL_DEPTH_COMPONENT:
574 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400575 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400576 {
Jamie Madill437fa652016-05-03 15:13:24 -0400577 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400578 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400579 }
580 if (target != GL_TEXTURE_2D)
581 {
Jamie Madill437fa652016-05-03 15:13:24 -0400582 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400583 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400584 }
585 // OES_depth_texture supports loading depth data and multiple levels,
586 // but ANGLE_depth_texture does not
587 if (pixels != NULL || level != 0)
588 {
Jamie Madill437fa652016-05-03 15:13:24 -0400589 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400590 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400591 }
592 break;
593 default:
594 break;
595 }
596
597 if (type == GL_FLOAT)
598 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400599 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400600 {
Jamie Madill437fa652016-05-03 15:13:24 -0400601 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400602 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400603 }
604 }
605 else if (type == GL_HALF_FLOAT_OES)
606 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400607 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400608 {
Jamie Madill437fa652016-05-03 15:13:24 -0400609 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400610 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400611 }
612 }
613 }
614
615 return true;
616}
617
Jamie Madillc29968b2016-01-20 11:17:23 -0500618bool ValidateES2CopyTexImageParameters(ValidationContext *context,
619 GLenum target,
620 GLint level,
621 GLenum internalformat,
622 bool isSubImage,
623 GLint xoffset,
624 GLint yoffset,
625 GLint x,
626 GLint y,
627 GLsizei width,
628 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400629 GLint border)
630{
Jamie Madill560a8d82014-05-21 13:06:20 -0400631 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400632
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500633 if (!ValidTexture2DDestinationTarget(context, target))
634 {
Jamie Madill437fa652016-05-03 15:13:24 -0400635 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500636 return false;
637 }
638
Jamie Madill560a8d82014-05-21 13:06:20 -0400639 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
640 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400641 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400642 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400643 }
644
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700645 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400646 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500647 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
648 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400649
650 // [OpenGL ES 2.0.24] table 3.9
651 if (isSubImage)
652 {
653 switch (textureFormat)
654 {
655 case GL_ALPHA:
656 if (colorbufferFormat != GL_ALPHA8_EXT &&
657 colorbufferFormat != GL_RGBA4 &&
658 colorbufferFormat != GL_RGB5_A1 &&
659 colorbufferFormat != GL_RGBA8_OES)
660 {
Jamie Madill437fa652016-05-03 15:13:24 -0400661 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400662 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400663 }
664 break;
665 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400666 if (colorbufferFormat != GL_R8_EXT &&
667 colorbufferFormat != GL_RG8_EXT &&
668 colorbufferFormat != GL_RGB565 &&
669 colorbufferFormat != GL_RGB8_OES &&
670 colorbufferFormat != GL_RGBA4 &&
671 colorbufferFormat != GL_RGB5_A1 &&
672 colorbufferFormat != GL_RGBA8_OES)
673 {
Jamie Madill437fa652016-05-03 15:13:24 -0400674 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400675 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400676 }
677 break;
678 case GL_RED_EXT:
679 if (colorbufferFormat != GL_R8_EXT &&
680 colorbufferFormat != GL_RG8_EXT &&
681 colorbufferFormat != GL_RGB565 &&
682 colorbufferFormat != GL_RGB8_OES &&
683 colorbufferFormat != GL_RGBA4 &&
684 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500685 colorbufferFormat != GL_RGBA8_OES &&
686 colorbufferFormat != GL_R32F &&
687 colorbufferFormat != GL_RG32F &&
688 colorbufferFormat != GL_RGB32F &&
689 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400690 {
Jamie Madill437fa652016-05-03 15:13:24 -0400691 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400692 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400693 }
694 break;
695 case GL_RG_EXT:
696 if (colorbufferFormat != GL_RG8_EXT &&
697 colorbufferFormat != GL_RGB565 &&
698 colorbufferFormat != GL_RGB8_OES &&
699 colorbufferFormat != GL_RGBA4 &&
700 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500701 colorbufferFormat != GL_RGBA8_OES &&
702 colorbufferFormat != GL_RG32F &&
703 colorbufferFormat != GL_RGB32F &&
704 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400705 {
Jamie Madill437fa652016-05-03 15:13:24 -0400706 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400707 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400708 }
709 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400710 case GL_RGB:
711 if (colorbufferFormat != GL_RGB565 &&
712 colorbufferFormat != GL_RGB8_OES &&
713 colorbufferFormat != GL_RGBA4 &&
714 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500715 colorbufferFormat != GL_RGBA8_OES &&
716 colorbufferFormat != GL_RGB32F &&
717 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400718 {
Jamie Madill437fa652016-05-03 15:13:24 -0400719 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400720 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400721 }
722 break;
723 case GL_LUMINANCE_ALPHA:
724 case GL_RGBA:
725 if (colorbufferFormat != GL_RGBA4 &&
726 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500727 colorbufferFormat != GL_RGBA8_OES &&
728 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400729 {
Jamie Madill437fa652016-05-03 15:13:24 -0400730 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400731 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400732 }
733 break;
734 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
735 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
736 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
737 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400738 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800739 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400740 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400741 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400742 case GL_DEPTH_COMPONENT:
743 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400744 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400745 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400747 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400748 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400749 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500750
751 if (internalFormatInfo.type == GL_FLOAT &&
752 !context->getExtensions().textureFloat)
753 {
Jamie Madill437fa652016-05-03 15:13:24 -0400754 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500755 return false;
756 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400757 }
758 else
759 {
760 switch (internalformat)
761 {
762 case GL_ALPHA:
763 if (colorbufferFormat != GL_ALPHA8_EXT &&
764 colorbufferFormat != GL_RGBA4 &&
765 colorbufferFormat != GL_RGB5_A1 &&
766 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500767 colorbufferFormat != GL_RGBA8_OES &&
768 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400769 {
Jamie Madill437fa652016-05-03 15:13:24 -0400770 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400771 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772 }
773 break;
774 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400775 if (colorbufferFormat != GL_R8_EXT &&
776 colorbufferFormat != GL_RG8_EXT &&
777 colorbufferFormat != GL_RGB565 &&
778 colorbufferFormat != GL_RGB8_OES &&
779 colorbufferFormat != GL_RGBA4 &&
780 colorbufferFormat != GL_RGB5_A1 &&
781 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500782 colorbufferFormat != GL_RGBA8_OES &&
783 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400784 {
Jamie Madill437fa652016-05-03 15:13:24 -0400785 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400786 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400787 }
788 break;
789 case GL_RED_EXT:
790 if (colorbufferFormat != GL_R8_EXT &&
791 colorbufferFormat != GL_RG8_EXT &&
792 colorbufferFormat != GL_RGB565 &&
793 colorbufferFormat != GL_RGB8_OES &&
794 colorbufferFormat != GL_RGBA4 &&
795 colorbufferFormat != GL_RGB5_A1 &&
796 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500797 colorbufferFormat != GL_RGBA8_OES &&
798 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400799 {
Jamie Madill437fa652016-05-03 15:13:24 -0400800 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400801 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400802 }
803 break;
804 case GL_RG_EXT:
805 if (colorbufferFormat != GL_RG8_EXT &&
806 colorbufferFormat != GL_RGB565 &&
807 colorbufferFormat != GL_RGB8_OES &&
808 colorbufferFormat != GL_RGBA4 &&
809 colorbufferFormat != GL_RGB5_A1 &&
810 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500811 colorbufferFormat != GL_RGBA8_OES &&
812 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400813 {
Jamie Madill437fa652016-05-03 15:13:24 -0400814 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400815 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400816 }
817 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 case GL_RGB:
819 if (colorbufferFormat != GL_RGB565 &&
820 colorbufferFormat != GL_RGB8_OES &&
821 colorbufferFormat != GL_RGBA4 &&
822 colorbufferFormat != GL_RGB5_A1 &&
823 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500824 colorbufferFormat != GL_RGBA8_OES &&
825 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826 {
Jamie Madill437fa652016-05-03 15:13:24 -0400827 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400828 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 }
830 break;
831 case GL_LUMINANCE_ALPHA:
832 case GL_RGBA:
833 if (colorbufferFormat != GL_RGBA4 &&
834 colorbufferFormat != GL_RGB5_A1 &&
835 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500836 colorbufferFormat != GL_RGBA8_OES &&
837 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 {
Jamie Madill437fa652016-05-03 15:13:24 -0400839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 }
842 break;
843 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
844 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400845 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 {
Jamie Madill437fa652016-05-03 15:13:24 -0400847 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400849 }
850 else
851 {
Jamie Madill437fa652016-05-03 15:13:24 -0400852 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400853 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854 }
855 break;
856 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400857 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 {
Jamie Madill437fa652016-05-03 15:13:24 -0400859 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400860 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 }
862 else
863 {
Jamie Madill437fa652016-05-03 15:13:24 -0400864 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400865 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 }
867 break;
868 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400869 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400870 {
Jamie Madill437fa652016-05-03 15:13:24 -0400871 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400872 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400873 }
874 else
875 {
Jamie Madill437fa652016-05-03 15:13:24 -0400876 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878 }
879 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400880 case GL_ETC1_RGB8_OES:
881 if (context->getExtensions().compressedETC1RGB8Texture)
882 {
Jamie Madill437fa652016-05-03 15:13:24 -0400883 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400884 return false;
885 }
886 else
887 {
Jamie Madill437fa652016-05-03 15:13:24 -0400888 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400889 return false;
890 }
891 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800892 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
893 if (context->getExtensions().lossyETCDecode)
894 {
Jamie Madill437fa652016-05-03 15:13:24 -0400895 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gonge3939b92015-12-01 15:36:51 -0800896 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
897 return false;
898 }
899 else
900 {
Jamie Madill437fa652016-05-03 15:13:24 -0400901 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800902 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
903 return false;
904 }
905 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400906 case GL_DEPTH_COMPONENT:
907 case GL_DEPTH_COMPONENT16:
908 case GL_DEPTH_COMPONENT32_OES:
909 case GL_DEPTH_STENCIL_OES:
910 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400911 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 {
Jamie Madill437fa652016-05-03 15:13:24 -0400913 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400914 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 }
916 else
917 {
Jamie Madill437fa652016-05-03 15:13:24 -0400918 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400919 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 }
921 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
925 }
926
Geoff Lang784a8fd2013-09-24 12:33:16 -0400927 // If width or height is zero, it is a no-op. Return false without setting an error.
928 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929}
930
Geoff Langb1196682014-07-23 13:47:29 -0400931bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 GLsizei width, GLsizei height)
933{
934 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
935 {
Jamie Madill437fa652016-05-03 15:13:24 -0400936 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400937 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400938 }
939
940 if (width < 1 || height < 1 || levels < 1)
941 {
Jamie Madill437fa652016-05-03 15:13:24 -0400942 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944 }
945
946 if (target == GL_TEXTURE_CUBE_MAP && width != height)
947 {
Jamie Madill437fa652016-05-03 15:13:24 -0400948 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 }
951
952 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
953 {
Jamie Madill437fa652016-05-03 15:13:24 -0400954 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 }
957
Geoff Lang5d601382014-07-22 15:14:06 -0400958 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
959 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 {
Jamie Madill437fa652016-05-03 15:13:24 -0400961 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 }
964
Geoff Langaae65a42014-05-26 12:43:44 -0400965 const gl::Caps &caps = context->getCaps();
966
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 switch (target)
968 {
969 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400970 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
971 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400972 {
Jamie Madill437fa652016-05-03 15:13:24 -0400973 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 }
976 break;
977 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400978 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
979 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 {
Jamie Madill437fa652016-05-03 15:13:24 -0400981 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400982 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 }
984 break;
985 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400986 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400988 }
989
Geoff Langc0b9ef42014-07-02 10:02:37 -0400990 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400991 {
992 if (!gl::isPow2(width) || !gl::isPow2(height))
993 {
Jamie Madill437fa652016-05-03 15:13:24 -0400994 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 }
997 }
998
999 switch (internalformat)
1000 {
1001 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1002 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001003 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 {
Jamie Madill437fa652016-05-03 15:13:24 -04001005 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001006 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 }
1008 break;
1009 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001010 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 {
Jamie Madill437fa652016-05-03 15:13:24 -04001012 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001013 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 }
1015 break;
1016 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001017 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Jamie Madill437fa652016-05-03 15:13:24 -04001019 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -04001023 case GL_ETC1_RGB8_OES:
1024 if (!context->getExtensions().compressedETC1RGB8Texture)
1025 {
Jamie Madill437fa652016-05-03 15:13:24 -04001026 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -04001027 return false;
1028 }
1029 break;
Minmin Gonge3939b92015-12-01 15:36:51 -08001030 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1031 if (!context->getExtensions().lossyETCDecode)
1032 {
Jamie Madill437fa652016-05-03 15:13:24 -04001033 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001034 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1035 return false;
1036 }
1037 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 case GL_RGBA32F_EXT:
1039 case GL_RGB32F_EXT:
1040 case GL_ALPHA32F_EXT:
1041 case GL_LUMINANCE32F_EXT:
1042 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001043 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001044 {
Jamie Madill437fa652016-05-03 15:13:24 -04001045 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001046 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001047 }
1048 break;
1049 case GL_RGBA16F_EXT:
1050 case GL_RGB16F_EXT:
1051 case GL_ALPHA16F_EXT:
1052 case GL_LUMINANCE16F_EXT:
1053 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001054 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 {
Jamie Madill437fa652016-05-03 15:13:24 -04001056 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 }
1059 break;
Geoff Lang632192d2013-10-04 13:40:46 -04001060 case GL_R8_EXT:
1061 case GL_RG8_EXT:
1062 case GL_R16F_EXT:
1063 case GL_RG16F_EXT:
1064 case GL_R32F_EXT:
1065 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001066 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -04001067 {
Jamie Madill437fa652016-05-03 15:13:24 -04001068 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001069 return false;
Geoff Lang632192d2013-10-04 13:40:46 -04001070 }
1071 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001072 case GL_DEPTH_COMPONENT16:
1073 case GL_DEPTH_COMPONENT32_OES:
1074 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001075 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 {
Jamie Madill437fa652016-05-03 15:13:24 -04001077 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001078 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 }
1080 if (target != GL_TEXTURE_2D)
1081 {
Jamie Madill437fa652016-05-03 15:13:24 -04001082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001084 }
1085 // ANGLE_depth_texture only supports 1-level textures
1086 if (levels != 1)
1087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 }
1091 break;
1092 default:
1093 break;
1094 }
1095
Geoff Lang691e58c2014-12-19 17:03:25 -05001096 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 if (!texture || texture->id() == 0)
1098 {
Jamie Madill437fa652016-05-03 15:13:24 -04001099 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001100 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001101 }
1102
Geoff Lang69cce582015-09-17 13:20:36 -04001103 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 {
Jamie Madill437fa652016-05-03 15:13:24 -04001105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
1109 return true;
1110}
1111
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112// check for combinations of format and type that are valid for ReadPixels
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001113bool ValidES2ReadFormatType(ValidationContext *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001114{
1115 switch (format)
1116 {
1117 case GL_RGBA:
1118 switch (type)
1119 {
1120 case GL_UNSIGNED_BYTE:
1121 break;
1122 default:
1123 return false;
1124 }
1125 break;
1126 case GL_BGRA_EXT:
1127 switch (type)
1128 {
1129 case GL_UNSIGNED_BYTE:
1130 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1131 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1132 break;
1133 default:
1134 return false;
1135 }
1136 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001137 case GL_RG_EXT:
1138 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001139 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001140 {
1141 return false;
1142 }
1143 switch (type)
1144 {
1145 case GL_UNSIGNED_BYTE:
1146 break;
1147 default:
1148 return false;
1149 }
1150 break;
1151
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001152 default:
1153 return false;
1154 }
1155 return true;
1156}
1157
Austin Kinross08332632015-05-05 13:35:47 -07001158bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1159 const GLenum *attachments)
1160{
Jamie Madillc29968b2016-01-20 11:17:23 -05001161 if (!context->getExtensions().discardFramebuffer)
1162 {
Jamie Madill437fa652016-05-03 15:13:24 -04001163 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001164 return false;
1165 }
1166
Austin Kinross08332632015-05-05 13:35:47 -07001167 bool defaultFramebuffer = false;
1168
1169 switch (target)
1170 {
1171 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001172 defaultFramebuffer =
1173 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1174 break;
Austin Kinross08332632015-05-05 13:35:47 -07001175 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001177 return false;
1178 }
1179
1180 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1181}
1182
Austin Kinrossbc781f32015-10-26 09:27:38 -07001183bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1184{
1185 if (!context->getExtensions().vertexArrayObject)
1186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001188 return false;
1189 }
1190
1191 return ValidateBindVertexArrayBase(context, array);
1192}
1193
1194bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1195{
1196 if (!context->getExtensions().vertexArrayObject)
1197 {
Jamie Madill437fa652016-05-03 15:13:24 -04001198 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001199 return false;
1200 }
1201
Olli Etuaho41997e72016-03-10 13:38:39 +02001202 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001203}
1204
1205bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1206{
1207 if (!context->getExtensions().vertexArrayObject)
1208 {
Jamie Madill437fa652016-05-03 15:13:24 -04001209 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001210 return false;
1211 }
1212
Olli Etuaho41997e72016-03-10 13:38:39 +02001213 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001214}
1215
1216bool ValidateIsVertexArrayOES(Context *context)
1217{
1218 if (!context->getExtensions().vertexArrayObject)
1219 {
Jamie Madill437fa652016-05-03 15:13:24 -04001220 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001221 return false;
1222 }
1223
1224 return true;
1225}
Geoff Langc5629752015-12-07 16:29:04 -05001226
1227bool ValidateProgramBinaryOES(Context *context,
1228 GLuint program,
1229 GLenum binaryFormat,
1230 const void *binary,
1231 GLint length)
1232{
1233 if (!context->getExtensions().getProgramBinary)
1234 {
Jamie Madill437fa652016-05-03 15:13:24 -04001235 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001236 return false;
1237 }
1238
1239 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1240}
1241
1242bool ValidateGetProgramBinaryOES(Context *context,
1243 GLuint program,
1244 GLsizei bufSize,
1245 GLsizei *length,
1246 GLenum *binaryFormat,
1247 void *binary)
1248{
1249 if (!context->getExtensions().getProgramBinary)
1250 {
Jamie Madill437fa652016-05-03 15:13:24 -04001251 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001252 return false;
1253 }
1254
1255 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1256}
Geoff Lange102fee2015-12-10 11:23:30 -05001257
Geoff Lang70d0f492015-12-10 17:45:46 -05001258static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1259{
1260 switch (source)
1261 {
1262 case GL_DEBUG_SOURCE_API:
1263 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1264 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1265 case GL_DEBUG_SOURCE_OTHER:
1266 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1267 return !mustBeThirdPartyOrApplication;
1268
1269 case GL_DEBUG_SOURCE_THIRD_PARTY:
1270 case GL_DEBUG_SOURCE_APPLICATION:
1271 return true;
1272
1273 default:
1274 return false;
1275 }
1276}
1277
1278static bool ValidDebugType(GLenum type)
1279{
1280 switch (type)
1281 {
1282 case GL_DEBUG_TYPE_ERROR:
1283 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1284 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1285 case GL_DEBUG_TYPE_PERFORMANCE:
1286 case GL_DEBUG_TYPE_PORTABILITY:
1287 case GL_DEBUG_TYPE_OTHER:
1288 case GL_DEBUG_TYPE_MARKER:
1289 case GL_DEBUG_TYPE_PUSH_GROUP:
1290 case GL_DEBUG_TYPE_POP_GROUP:
1291 return true;
1292
1293 default:
1294 return false;
1295 }
1296}
1297
1298static bool ValidDebugSeverity(GLenum severity)
1299{
1300 switch (severity)
1301 {
1302 case GL_DEBUG_SEVERITY_HIGH:
1303 case GL_DEBUG_SEVERITY_MEDIUM:
1304 case GL_DEBUG_SEVERITY_LOW:
1305 case GL_DEBUG_SEVERITY_NOTIFICATION:
1306 return true;
1307
1308 default:
1309 return false;
1310 }
1311}
1312
Geoff Lange102fee2015-12-10 11:23:30 -05001313bool ValidateDebugMessageControlKHR(Context *context,
1314 GLenum source,
1315 GLenum type,
1316 GLenum severity,
1317 GLsizei count,
1318 const GLuint *ids,
1319 GLboolean enabled)
1320{
1321 if (!context->getExtensions().debug)
1322 {
Jamie Madill437fa652016-05-03 15:13:24 -04001323 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001324 return false;
1325 }
1326
Geoff Lang70d0f492015-12-10 17:45:46 -05001327 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1328 {
Jamie Madill437fa652016-05-03 15:13:24 -04001329 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001330 return false;
1331 }
1332
1333 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1334 {
Jamie Madill437fa652016-05-03 15:13:24 -04001335 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001336 return false;
1337 }
1338
1339 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1340 {
Jamie Madill437fa652016-05-03 15:13:24 -04001341 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001342 return false;
1343 }
1344
1345 if (count > 0)
1346 {
1347 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1348 {
Jamie Madill437fa652016-05-03 15:13:24 -04001349 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001350 GL_INVALID_OPERATION,
1351 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1352 return false;
1353 }
1354
1355 if (severity != GL_DONT_CARE)
1356 {
Jamie Madill437fa652016-05-03 15:13:24 -04001357 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001358 Error(GL_INVALID_OPERATION,
1359 "If count is greater than zero, severity must be GL_DONT_CARE."));
1360 return false;
1361 }
1362 }
1363
Geoff Lange102fee2015-12-10 11:23:30 -05001364 return true;
1365}
1366
1367bool ValidateDebugMessageInsertKHR(Context *context,
1368 GLenum source,
1369 GLenum type,
1370 GLuint id,
1371 GLenum severity,
1372 GLsizei length,
1373 const GLchar *buf)
1374{
1375 if (!context->getExtensions().debug)
1376 {
Jamie Madill437fa652016-05-03 15:13:24 -04001377 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001378 return false;
1379 }
1380
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001381 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001382 {
1383 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1384 // not generate an error.
1385 return false;
1386 }
1387
1388 if (!ValidDebugSeverity(severity))
1389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001391 return false;
1392 }
1393
1394 if (!ValidDebugType(type))
1395 {
Jamie Madill437fa652016-05-03 15:13:24 -04001396 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001397 return false;
1398 }
1399
1400 if (!ValidDebugSource(source, true))
1401 {
Jamie Madill437fa652016-05-03 15:13:24 -04001402 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001403 return false;
1404 }
1405
1406 size_t messageLength = (length < 0) ? strlen(buf) : length;
1407 if (messageLength > context->getExtensions().maxDebugMessageLength)
1408 {
Jamie Madill437fa652016-05-03 15:13:24 -04001409 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001410 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1411 return false;
1412 }
1413
Geoff Lange102fee2015-12-10 11:23:30 -05001414 return true;
1415}
1416
1417bool ValidateDebugMessageCallbackKHR(Context *context,
1418 GLDEBUGPROCKHR callback,
1419 const void *userParam)
1420{
1421 if (!context->getExtensions().debug)
1422 {
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001424 return false;
1425 }
1426
Geoff Lange102fee2015-12-10 11:23:30 -05001427 return true;
1428}
1429
1430bool ValidateGetDebugMessageLogKHR(Context *context,
1431 GLuint count,
1432 GLsizei bufSize,
1433 GLenum *sources,
1434 GLenum *types,
1435 GLuint *ids,
1436 GLenum *severities,
1437 GLsizei *lengths,
1438 GLchar *messageLog)
1439{
1440 if (!context->getExtensions().debug)
1441 {
Jamie Madill437fa652016-05-03 15:13:24 -04001442 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001443 return false;
1444 }
1445
Geoff Lang70d0f492015-12-10 17:45:46 -05001446 if (bufSize < 0 && messageLog != nullptr)
1447 {
Jamie Madill437fa652016-05-03 15:13:24 -04001448 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001449 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1450 return false;
1451 }
1452
Geoff Lange102fee2015-12-10 11:23:30 -05001453 return true;
1454}
1455
1456bool ValidatePushDebugGroupKHR(Context *context,
1457 GLenum source,
1458 GLuint id,
1459 GLsizei length,
1460 const GLchar *message)
1461{
1462 if (!context->getExtensions().debug)
1463 {
Jamie Madill437fa652016-05-03 15:13:24 -04001464 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001465 return false;
1466 }
1467
Geoff Lang70d0f492015-12-10 17:45:46 -05001468 if (!ValidDebugSource(source, true))
1469 {
Jamie Madill437fa652016-05-03 15:13:24 -04001470 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001471 return false;
1472 }
1473
1474 size_t messageLength = (length < 0) ? strlen(message) : length;
1475 if (messageLength > context->getExtensions().maxDebugMessageLength)
1476 {
Jamie Madill437fa652016-05-03 15:13:24 -04001477 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001478 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1479 return false;
1480 }
1481
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001482 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001483 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1484 {
Jamie Madill437fa652016-05-03 15:13:24 -04001485 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001486 Error(GL_STACK_OVERFLOW,
1487 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1488 return false;
1489 }
1490
Geoff Lange102fee2015-12-10 11:23:30 -05001491 return true;
1492}
1493
1494bool ValidatePopDebugGroupKHR(Context *context)
1495{
1496 if (!context->getExtensions().debug)
1497 {
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001499 return false;
1500 }
1501
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001502 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001503 if (currentStackSize <= 1)
1504 {
Jamie Madill437fa652016-05-03 15:13:24 -04001505 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001506 return false;
1507 }
1508
1509 return true;
1510}
1511
1512static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1513{
1514 switch (identifier)
1515 {
1516 case GL_BUFFER:
1517 if (context->getBuffer(name) == nullptr)
1518 {
Jamie Madill437fa652016-05-03 15:13:24 -04001519 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001520 return false;
1521 }
1522 return true;
1523
1524 case GL_SHADER:
1525 if (context->getShader(name) == nullptr)
1526 {
Jamie Madill437fa652016-05-03 15:13:24 -04001527 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001528 return false;
1529 }
1530 return true;
1531
1532 case GL_PROGRAM:
1533 if (context->getProgram(name) == nullptr)
1534 {
Jamie Madill437fa652016-05-03 15:13:24 -04001535 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001536 return false;
1537 }
1538 return true;
1539
1540 case GL_VERTEX_ARRAY:
1541 if (context->getVertexArray(name) == nullptr)
1542 {
Jamie Madill437fa652016-05-03 15:13:24 -04001543 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001544 return false;
1545 }
1546 return true;
1547
1548 case GL_QUERY:
1549 if (context->getQuery(name) == nullptr)
1550 {
Jamie Madill437fa652016-05-03 15:13:24 -04001551 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001552 return false;
1553 }
1554 return true;
1555
1556 case GL_TRANSFORM_FEEDBACK:
1557 if (context->getTransformFeedback(name) == nullptr)
1558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001560 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1561 return false;
1562 }
1563 return true;
1564
1565 case GL_SAMPLER:
1566 if (context->getSampler(name) == nullptr)
1567 {
Jamie Madill437fa652016-05-03 15:13:24 -04001568 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001569 return false;
1570 }
1571 return true;
1572
1573 case GL_TEXTURE:
1574 if (context->getTexture(name) == nullptr)
1575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001577 return false;
1578 }
1579 return true;
1580
1581 case GL_RENDERBUFFER:
1582 if (context->getRenderbuffer(name) == nullptr)
1583 {
Jamie Madill437fa652016-05-03 15:13:24 -04001584 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001585 return false;
1586 }
1587 return true;
1588
1589 case GL_FRAMEBUFFER:
1590 if (context->getFramebuffer(name) == nullptr)
1591 {
Jamie Madill437fa652016-05-03 15:13:24 -04001592 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001593 return false;
1594 }
1595 return true;
1596
1597 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001598 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001599 return false;
1600 }
1601
Geoff Lange102fee2015-12-10 11:23:30 -05001602 return true;
1603}
1604
1605bool ValidateObjectLabelKHR(Context *context,
1606 GLenum identifier,
1607 GLuint name,
1608 GLsizei length,
1609 const GLchar *label)
1610{
1611 if (!context->getExtensions().debug)
1612 {
Jamie Madill437fa652016-05-03 15:13:24 -04001613 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001614 return false;
1615 }
1616
Geoff Lang70d0f492015-12-10 17:45:46 -05001617 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1618 {
1619 return false;
1620 }
1621
1622 size_t labelLength = (length < 0) ? strlen(label) : length;
1623 if (labelLength > context->getExtensions().maxLabelLength)
1624 {
Jamie Madill437fa652016-05-03 15:13:24 -04001625 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001626 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1627 return false;
1628 }
1629
Geoff Lange102fee2015-12-10 11:23:30 -05001630 return true;
1631}
1632
1633bool ValidateGetObjectLabelKHR(Context *context,
1634 GLenum identifier,
1635 GLuint name,
1636 GLsizei bufSize,
1637 GLsizei *length,
1638 GLchar *label)
1639{
1640 if (!context->getExtensions().debug)
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001643 return false;
1644 }
1645
Geoff Lang70d0f492015-12-10 17:45:46 -05001646 if (bufSize < 0)
1647 {
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001649 return false;
1650 }
1651
1652 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1653 {
1654 return false;
1655 }
1656
1657 // Can no-op if bufSize is zero.
1658 return bufSize > 0;
1659}
1660
1661static bool ValidateObjectPtrName(Context *context, const void *ptr)
1662{
1663 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1664 {
Jamie Madill437fa652016-05-03 15:13:24 -04001665 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001666 return false;
1667 }
1668
Geoff Lange102fee2015-12-10 11:23:30 -05001669 return true;
1670}
1671
1672bool ValidateObjectPtrLabelKHR(Context *context,
1673 const void *ptr,
1674 GLsizei length,
1675 const GLchar *label)
1676{
1677 if (!context->getExtensions().debug)
1678 {
Jamie Madill437fa652016-05-03 15:13:24 -04001679 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001680 return false;
1681 }
1682
Geoff Lang70d0f492015-12-10 17:45:46 -05001683 if (!ValidateObjectPtrName(context, ptr))
1684 {
1685 return false;
1686 }
1687
1688 size_t labelLength = (length < 0) ? strlen(label) : length;
1689 if (labelLength > context->getExtensions().maxLabelLength)
1690 {
Jamie Madill437fa652016-05-03 15:13:24 -04001691 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001692 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1693 return false;
1694 }
1695
Geoff Lange102fee2015-12-10 11:23:30 -05001696 return true;
1697}
1698
1699bool ValidateGetObjectPtrLabelKHR(Context *context,
1700 const void *ptr,
1701 GLsizei bufSize,
1702 GLsizei *length,
1703 GLchar *label)
1704{
1705 if (!context->getExtensions().debug)
1706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001708 return false;
1709 }
1710
Geoff Lang70d0f492015-12-10 17:45:46 -05001711 if (bufSize < 0)
1712 {
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001714 return false;
1715 }
1716
1717 if (!ValidateObjectPtrName(context, ptr))
1718 {
1719 return false;
1720 }
1721
1722 // Can no-op if bufSize is zero.
1723 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001724}
1725
1726bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1727{
1728 if (!context->getExtensions().debug)
1729 {
Jamie Madill437fa652016-05-03 15:13:24 -04001730 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001731 return false;
1732 }
1733
Geoff Lang70d0f492015-12-10 17:45:46 -05001734 // TODO: represent this in Context::getQueryParameterInfo.
1735 switch (pname)
1736 {
1737 case GL_DEBUG_CALLBACK_FUNCTION:
1738 case GL_DEBUG_CALLBACK_USER_PARAM:
1739 break;
1740
1741 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001742 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001743 return false;
1744 }
1745
Geoff Lange102fee2015-12-10 11:23:30 -05001746 return true;
1747}
Jamie Madillc29968b2016-01-20 11:17:23 -05001748
1749bool ValidateBlitFramebufferANGLE(Context *context,
1750 GLint srcX0,
1751 GLint srcY0,
1752 GLint srcX1,
1753 GLint srcY1,
1754 GLint dstX0,
1755 GLint dstY0,
1756 GLint dstX1,
1757 GLint dstY1,
1758 GLbitfield mask,
1759 GLenum filter)
1760{
1761 if (!context->getExtensions().framebufferBlit)
1762 {
Jamie Madill437fa652016-05-03 15:13:24 -04001763 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001764 return false;
1765 }
1766
1767 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1768 {
1769 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001770 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001771 GL_INVALID_OPERATION,
1772 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1773 return false;
1774 }
1775
1776 if (filter == GL_LINEAR)
1777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001779 return false;
1780 }
1781
Jamie Madill51f40ec2016-06-15 14:06:00 -04001782 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1783 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001784
1785 if (mask & GL_COLOR_BUFFER_BIT)
1786 {
1787 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1788 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1789
1790 if (readColorAttachment && drawColorAttachment)
1791 {
1792 if (!(readColorAttachment->type() == GL_TEXTURE &&
1793 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1794 readColorAttachment->type() != GL_RENDERBUFFER &&
1795 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1796 {
Jamie Madill437fa652016-05-03 15:13:24 -04001797 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001798 return false;
1799 }
1800
Geoff Langa15472a2015-08-11 11:48:03 -04001801 for (size_t drawbufferIdx = 0;
1802 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001803 {
Geoff Langa15472a2015-08-11 11:48:03 -04001804 const FramebufferAttachment *attachment =
1805 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1806 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001807 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001808 if (!(attachment->type() == GL_TEXTURE &&
1809 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1810 attachment->type() != GL_RENDERBUFFER &&
1811 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1812 {
Jamie Madill437fa652016-05-03 15:13:24 -04001813 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001814 return false;
1815 }
1816
1817 // Return an error if the destination formats do not match
1818 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1819 {
Jamie Madill437fa652016-05-03 15:13:24 -04001820 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001821 return false;
1822 }
1823 }
1824 }
1825
Jamie Madill51f40ec2016-06-15 14:06:00 -04001826 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001827 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1828 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
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 }
1835
1836 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1837 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1838 for (size_t i = 0; i < 2; i++)
1839 {
1840 if (mask & masks[i])
1841 {
1842 const FramebufferAttachment *readBuffer =
1843 readFramebuffer->getAttachment(attachments[i]);
1844 const FramebufferAttachment *drawBuffer =
1845 drawFramebuffer->getAttachment(attachments[i]);
1846
1847 if (readBuffer && drawBuffer)
1848 {
1849 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1850 dstX0, dstY0, dstX1, dstY1))
1851 {
1852 // only whole-buffer copies are permitted
1853 ERR(
1854 "Only whole-buffer depth and stencil blits are supported by this "
1855 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001856 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001857 return false;
1858 }
1859
1860 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 return false;
1864 }
1865 }
1866 }
1867 }
1868
1869 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1870 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001871}
Jamie Madillc29968b2016-01-20 11:17:23 -05001872
1873bool ValidateClear(ValidationContext *context, GLbitfield mask)
1874{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001875 auto fbo = context->getGLState().getDrawFramebuffer();
1876 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001877 {
Jamie Madill437fa652016-05-03 15:13:24 -04001878 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001879 return false;
1880 }
1881
1882 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1883 {
Jamie Madill437fa652016-05-03 15:13:24 -04001884 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001885 return false;
1886 }
1887
1888 return true;
1889}
1890
1891bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1892{
1893 if (!context->getExtensions().drawBuffers)
1894 {
Jamie Madill437fa652016-05-03 15:13:24 -04001895 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001896 return false;
1897 }
1898
1899 return ValidateDrawBuffersBase(context, n, bufs);
1900}
1901
Jamie Madill73a84962016-02-12 09:27:23 -05001902bool ValidateTexImage2D(Context *context,
1903 GLenum target,
1904 GLint level,
1905 GLint internalformat,
1906 GLsizei width,
1907 GLsizei height,
1908 GLint border,
1909 GLenum format,
1910 GLenum type,
1911 const GLvoid *pixels)
1912{
1913 if (context->getClientVersion() < 3)
1914 {
1915 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1916 0, 0, width, height, border, format, type, pixels);
1917 }
1918
1919 ASSERT(context->getClientVersion() >= 3);
1920 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1921 0, 0, width, height, 1, border, format, type, pixels);
1922}
1923
1924bool ValidateTexSubImage2D(Context *context,
1925 GLenum target,
1926 GLint level,
1927 GLint xoffset,
1928 GLint yoffset,
1929 GLsizei width,
1930 GLsizei height,
1931 GLenum format,
1932 GLenum type,
1933 const GLvoid *pixels)
1934{
1935
1936 if (context->getClientVersion() < 3)
1937 {
1938 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1939 yoffset, width, height, 0, format, type, pixels);
1940 }
1941
1942 ASSERT(context->getClientVersion() >= 3);
1943 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1944 yoffset, 0, width, height, 1, 0, format, type, pixels);
1945}
1946
1947bool ValidateCompressedTexImage2D(Context *context,
1948 GLenum target,
1949 GLint level,
1950 GLenum internalformat,
1951 GLsizei width,
1952 GLsizei height,
1953 GLint border,
1954 GLsizei imageSize,
1955 const GLvoid *data)
1956{
1957 if (context->getClientVersion() < 3)
1958 {
1959 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1960 0, width, height, border, GL_NONE, GL_NONE, data))
1961 {
1962 return false;
1963 }
1964 }
1965 else
1966 {
1967 ASSERT(context->getClientVersion() >= 3);
1968 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1969 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1970 data))
1971 {
1972 return false;
1973 }
1974 }
1975
1976 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001977 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001978 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001979 if (blockSizeOrErr.isError())
1980 {
1981 context->handleError(blockSizeOrErr.getError());
1982 return false;
1983 }
1984
1985 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001986 {
Jamie Madill437fa652016-05-03 15:13:24 -04001987 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001988 return false;
1989 }
1990
1991 return true;
1992}
1993
1994bool ValidateCompressedTexSubImage2D(Context *context,
1995 GLenum target,
1996 GLint level,
1997 GLint xoffset,
1998 GLint yoffset,
1999 GLsizei width,
2000 GLsizei height,
2001 GLenum format,
2002 GLsizei imageSize,
2003 const GLvoid *data)
2004{
2005 if (context->getClientVersion() < 3)
2006 {
2007 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2008 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2009 {
2010 return false;
2011 }
2012 }
2013 else
2014 {
2015 ASSERT(context->getClientVersion() >= 3);
2016 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2017 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2018 data))
2019 {
2020 return false;
2021 }
2022 }
2023
2024 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002025 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002026 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002027 if (blockSizeOrErr.isError())
2028 {
2029 context->handleError(blockSizeOrErr.getError());
2030 return false;
2031 }
2032
2033 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002036 return false;
2037 }
2038
2039 return true;
2040}
2041
Olli Etuaho4f667482016-03-30 15:56:35 +03002042bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2043{
2044 if (!context->getExtensions().mapBuffer)
2045 {
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002047 return false;
2048 }
2049
2050 return ValidateGetBufferPointervBase(context, target, pname, params);
2051}
2052
2053bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2054{
2055 if (!context->getExtensions().mapBuffer)
2056 {
Jamie Madill437fa652016-05-03 15:13:24 -04002057 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002058 return false;
2059 }
2060
2061 if (!ValidBufferTarget(context, target))
2062 {
Jamie Madill437fa652016-05-03 15:13:24 -04002063 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002064 return false;
2065 }
2066
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002067 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002068
2069 if (buffer == nullptr)
2070 {
Jamie Madill437fa652016-05-03 15:13:24 -04002071 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002072 return false;
2073 }
2074
2075 if (access != GL_WRITE_ONLY_OES)
2076 {
Jamie Madill437fa652016-05-03 15:13:24 -04002077 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002078 return false;
2079 }
2080
2081 if (buffer->isMapped())
2082 {
Jamie Madill437fa652016-05-03 15:13:24 -04002083 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002084 return false;
2085 }
2086
2087 return true;
2088}
2089
2090bool ValidateUnmapBufferOES(Context *context, GLenum target)
2091{
2092 if (!context->getExtensions().mapBuffer)
2093 {
Jamie Madill437fa652016-05-03 15:13:24 -04002094 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002095 return false;
2096 }
2097
2098 return ValidateUnmapBufferBase(context, target);
2099}
2100
2101bool ValidateMapBufferRangeEXT(Context *context,
2102 GLenum target,
2103 GLintptr offset,
2104 GLsizeiptr length,
2105 GLbitfield access)
2106{
2107 if (!context->getExtensions().mapBufferRange)
2108 {
Jamie Madill437fa652016-05-03 15:13:24 -04002109 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002110 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2111 return false;
2112 }
2113
2114 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2115}
2116
2117bool ValidateFlushMappedBufferRangeEXT(Context *context,
2118 GLenum target,
2119 GLintptr offset,
2120 GLsizeiptr length)
2121{
2122 if (!context->getExtensions().mapBufferRange)
2123 {
Jamie Madill437fa652016-05-03 15:13:24 -04002124 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002125 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2126 return false;
2127 }
2128
2129 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2130}
2131
Ian Ewell54f87462016-03-10 13:47:21 -05002132bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2133{
2134 Texture *textureObject = context->getTexture(texture);
2135 if (textureObject && textureObject->getTarget() != target && texture != 0)
2136 {
Jamie Madill437fa652016-05-03 15:13:24 -04002137 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002138 return false;
2139 }
2140
2141 switch (target)
2142 {
2143 case GL_TEXTURE_2D:
2144 case GL_TEXTURE_CUBE_MAP:
2145 break;
2146
2147 case GL_TEXTURE_3D:
2148 case GL_TEXTURE_2D_ARRAY:
2149 if (context->getClientVersion() < 3)
2150 {
Jamie Madill437fa652016-05-03 15:13:24 -04002151 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002152 return false;
2153 }
2154 break;
2155 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002156 if (!context->getExtensions().eglImageExternal &&
2157 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002158 {
Jamie Madill437fa652016-05-03 15:13:24 -04002159 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002160 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2161 return false;
2162 }
2163 break;
2164 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002165 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002166 return false;
2167 }
2168
2169 return true;
2170}
2171
Geoff Langd8605522016-04-13 10:19:12 -04002172bool ValidateBindUniformLocationCHROMIUM(Context *context,
2173 GLuint program,
2174 GLint location,
2175 const GLchar *name)
2176{
2177 if (!context->getExtensions().bindUniformLocation)
2178 {
Jamie Madill437fa652016-05-03 15:13:24 -04002179 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002180 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2181 return false;
2182 }
2183
2184 Program *programObject = GetValidProgram(context, program);
2185 if (!programObject)
2186 {
2187 return false;
2188 }
2189
2190 if (location < 0)
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002193 return false;
2194 }
2195
2196 const Caps &caps = context->getCaps();
2197 if (static_cast<size_t>(location) >=
2198 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002201 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2202 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2203 return false;
2204 }
2205
2206 if (strncmp(name, "gl_", 3) == 0)
2207 {
Jamie Madill437fa652016-05-03 15:13:24 -04002208 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002209 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2210 return false;
2211 }
2212
2213 return true;
2214}
2215
Jamie Madille2e406c2016-06-02 13:04:10 -04002216bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002217{
2218 if (!context->getExtensions().framebufferMixedSamples)
2219 {
2220 context->handleError(
2221 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2222 return false;
2223 }
2224 switch (components)
2225 {
2226 case GL_RGB:
2227 case GL_RGBA:
2228 case GL_ALPHA:
2229 case GL_NONE:
2230 break;
2231 default:
2232 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002233 Error(GL_INVALID_ENUM,
2234 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002235 return false;
2236 }
2237
2238 return true;
2239}
2240
Sami Väisänene45e53b2016-05-25 10:36:04 +03002241// CHROMIUM_path_rendering
2242
2243bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2244{
2245 if (!context->getExtensions().pathRendering)
2246 {
2247 context->handleError(
2248 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2249 return false;
2250 }
2251 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2252 {
2253 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2254 return false;
2255 }
2256 if (matrix == nullptr)
2257 {
2258 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2259 return false;
2260 }
2261 return true;
2262}
2263
2264bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2265{
2266 if (!context->getExtensions().pathRendering)
2267 {
2268 context->handleError(
2269 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2270 return false;
2271 }
2272 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2273 {
2274 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2275 return false;
2276 }
2277 return true;
2278}
2279
2280bool ValidateGenPaths(Context *context, GLsizei range)
2281{
2282 if (!context->getExtensions().pathRendering)
2283 {
2284 context->handleError(
2285 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2286 return false;
2287 }
2288
2289 // range = 0 is undefined in NV_path_rendering.
2290 // we add stricter semantic check here and require a non zero positive range.
2291 if (range <= 0)
2292 {
2293 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2294 return false;
2295 }
2296
2297 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2298 {
2299 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2300 return false;
2301 }
2302
2303 return true;
2304}
2305
2306bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2307{
2308 if (!context->getExtensions().pathRendering)
2309 {
2310 context->handleError(
2311 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2312 return false;
2313 }
2314
2315 // range = 0 is undefined in NV_path_rendering.
2316 // we add stricter semantic check here and require a non zero positive range.
2317 if (range <= 0)
2318 {
2319 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2320 return false;
2321 }
2322
2323 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2324 checkedRange += range;
2325
2326 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2327 {
2328 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2329 return false;
2330 }
2331 return true;
2332}
2333
2334bool ValidatePathCommands(Context *context,
2335 GLuint path,
2336 GLsizei numCommands,
2337 const GLubyte *commands,
2338 GLsizei numCoords,
2339 GLenum coordType,
2340 const void *coords)
2341{
2342 if (!context->getExtensions().pathRendering)
2343 {
2344 context->handleError(
2345 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2346 return false;
2347 }
2348 if (!context->hasPath(path))
2349 {
2350 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2351 return false;
2352 }
2353
2354 if (numCommands < 0)
2355 {
2356 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2357 return false;
2358 }
2359 else if (numCommands > 0)
2360 {
2361 if (!commands)
2362 {
2363 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2364 return false;
2365 }
2366 }
2367
2368 if (numCoords < 0)
2369 {
2370 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2371 return false;
2372 }
2373 else if (numCoords > 0)
2374 {
2375 if (!coords)
2376 {
2377 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2378 return false;
2379 }
2380 }
2381
2382 std::uint32_t coordTypeSize = 0;
2383 switch (coordType)
2384 {
2385 case GL_BYTE:
2386 coordTypeSize = sizeof(GLbyte);
2387 break;
2388
2389 case GL_UNSIGNED_BYTE:
2390 coordTypeSize = sizeof(GLubyte);
2391 break;
2392
2393 case GL_SHORT:
2394 coordTypeSize = sizeof(GLshort);
2395 break;
2396
2397 case GL_UNSIGNED_SHORT:
2398 coordTypeSize = sizeof(GLushort);
2399 break;
2400
2401 case GL_FLOAT:
2402 coordTypeSize = sizeof(GLfloat);
2403 break;
2404
2405 default:
2406 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2407 return false;
2408 }
2409
2410 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2411 checkedSize += (coordTypeSize * numCoords);
2412 if (!checkedSize.IsValid())
2413 {
2414 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2415 return false;
2416 }
2417
2418 // early return skips command data validation when it doesn't exist.
2419 if (!commands)
2420 return true;
2421
2422 GLsizei expectedNumCoords = 0;
2423 for (GLsizei i = 0; i < numCommands; ++i)
2424 {
2425 switch (commands[i])
2426 {
2427 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2428 break;
2429 case GL_MOVE_TO_CHROMIUM:
2430 case GL_LINE_TO_CHROMIUM:
2431 expectedNumCoords += 2;
2432 break;
2433 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2434 expectedNumCoords += 4;
2435 break;
2436 case GL_CUBIC_CURVE_TO_CHROMIUM:
2437 expectedNumCoords += 6;
2438 break;
2439 case GL_CONIC_CURVE_TO_CHROMIUM:
2440 expectedNumCoords += 5;
2441 break;
2442 default:
2443 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2444 return false;
2445 }
2446 }
2447 if (expectedNumCoords != numCoords)
2448 {
2449 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2450 return false;
2451 }
2452
2453 return true;
2454}
2455
2456bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2457{
2458 if (!context->getExtensions().pathRendering)
2459 {
2460 context->handleError(
2461 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2462 return false;
2463 }
2464 if (!context->hasPath(path))
2465 {
2466 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2467 return false;
2468 }
2469
2470 switch (pname)
2471 {
2472 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2473 if (value < 0.0f)
2474 {
2475 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2476 return false;
2477 }
2478 break;
2479 case GL_PATH_END_CAPS_CHROMIUM:
2480 switch (static_cast<GLenum>(value))
2481 {
2482 case GL_FLAT_CHROMIUM:
2483 case GL_SQUARE_CHROMIUM:
2484 case GL_ROUND_CHROMIUM:
2485 break;
2486 default:
2487 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2488 return false;
2489 }
2490 break;
2491 case GL_PATH_JOIN_STYLE_CHROMIUM:
2492 switch (static_cast<GLenum>(value))
2493 {
2494 case GL_MITER_REVERT_CHROMIUM:
2495 case GL_BEVEL_CHROMIUM:
2496 case GL_ROUND_CHROMIUM:
2497 break;
2498 default:
2499 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2500 return false;
2501 }
2502 case GL_PATH_MITER_LIMIT_CHROMIUM:
2503 if (value < 0.0f)
2504 {
2505 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2506 return false;
2507 }
2508 break;
2509
2510 case GL_PATH_STROKE_BOUND_CHROMIUM:
2511 // no errors, only clamping.
2512 break;
2513
2514 default:
2515 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2516 return false;
2517 }
2518 return true;
2519}
2520
2521bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2522{
2523 if (!context->getExtensions().pathRendering)
2524 {
2525 context->handleError(
2526 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2527 return false;
2528 }
2529
2530 if (!context->hasPath(path))
2531 {
2532 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2533 return false;
2534 }
2535 if (!value)
2536 {
2537 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2538 return false;
2539 }
2540
2541 switch (pname)
2542 {
2543 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2544 case GL_PATH_END_CAPS_CHROMIUM:
2545 case GL_PATH_JOIN_STYLE_CHROMIUM:
2546 case GL_PATH_MITER_LIMIT_CHROMIUM:
2547 case GL_PATH_STROKE_BOUND_CHROMIUM:
2548 break;
2549
2550 default:
2551 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2552 return false;
2553 }
2554
2555 return true;
2556}
2557
2558bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2559{
2560 if (!context->getExtensions().pathRendering)
2561 {
2562 context->handleError(
2563 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2564 return false;
2565 }
2566
2567 switch (func)
2568 {
2569 case GL_NEVER:
2570 case GL_ALWAYS:
2571 case GL_LESS:
2572 case GL_LEQUAL:
2573 case GL_EQUAL:
2574 case GL_GEQUAL:
2575 case GL_GREATER:
2576 case GL_NOTEQUAL:
2577 break;
2578 default:
2579 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2580 return false;
2581 }
2582
2583 return true;
2584}
2585
2586// Note that the spec specifies that for the path drawing commands
2587// if the path object is not an existing path object the command
2588// does nothing and no error is generated.
2589// However if the path object exists but has not been specified any
2590// commands then an error is generated.
2591
2592bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2593{
2594 if (!context->getExtensions().pathRendering)
2595 {
2596 context->handleError(
2597 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2598 return false;
2599 }
2600 if (context->hasPath(path) && !context->hasPathData(path))
2601 {
2602 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2603 return false;
2604 }
2605
2606 switch (fillMode)
2607 {
2608 case GL_COUNT_UP_CHROMIUM:
2609 case GL_COUNT_DOWN_CHROMIUM:
2610 break;
2611 default:
2612 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2613 return false;
2614 }
2615
2616 if (!isPow2(mask + 1))
2617 {
2618 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2619 return false;
2620 }
2621
2622 return true;
2623}
2624
2625bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2626{
2627 if (!context->getExtensions().pathRendering)
2628 {
2629 context->handleError(
2630 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2631 return false;
2632 }
2633 if (context->hasPath(path) && !context->hasPathData(path))
2634 {
2635 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2636 return false;
2637 }
2638
2639 return true;
2640}
2641
2642bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
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 object."));
2653 return false;
2654 }
2655
2656 switch (coverMode)
2657 {
2658 case GL_CONVEX_HULL_CHROMIUM:
2659 case GL_BOUNDING_BOX_CHROMIUM:
2660 break;
2661 default:
2662 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2663 return false;
2664 }
2665 return true;
2666}
2667
2668bool ValidateStencilThenCoverFillPath(Context *context,
2669 GLuint path,
2670 GLenum fillMode,
2671 GLuint mask,
2672 GLenum coverMode)
2673{
2674 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2675 ValidateCoverPath(context, path, coverMode);
2676}
2677
2678bool ValidateStencilThenCoverStrokePath(Context *context,
2679 GLuint path,
2680 GLint reference,
2681 GLuint mask,
2682 GLenum coverMode)
2683{
2684 return ValidateStencilStrokePath(context, path, reference, mask) &&
2685 ValidateCoverPath(context, path, coverMode);
2686}
2687
2688bool ValidateIsPath(Context *context)
2689{
2690 if (!context->getExtensions().pathRendering)
2691 {
2692 context->handleError(
2693 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2694 return false;
2695 }
2696 return true;
2697}
2698
Sami Väisänend59ca052016-06-21 16:10:00 +03002699bool ValidateCoverFillPathInstanced(Context *context,
2700 GLsizei numPaths,
2701 GLenum pathNameType,
2702 const void *paths,
2703 GLuint pathBase,
2704 GLenum coverMode,
2705 GLenum transformType,
2706 const GLfloat *transformValues)
2707{
2708 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2709 transformType, transformValues))
2710 return false;
2711
2712 switch (coverMode)
2713 {
2714 case GL_CONVEX_HULL_CHROMIUM:
2715 case GL_BOUNDING_BOX_CHROMIUM:
2716 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2717 break;
2718 default:
2719 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2720 return false;
2721 }
2722
2723 return true;
2724}
2725
2726bool ValidateCoverStrokePathInstanced(Context *context,
2727 GLsizei numPaths,
2728 GLenum pathNameType,
2729 const void *paths,
2730 GLuint pathBase,
2731 GLenum coverMode,
2732 GLenum transformType,
2733 const GLfloat *transformValues)
2734{
2735 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2736 transformType, transformValues))
2737 return false;
2738
2739 switch (coverMode)
2740 {
2741 case GL_CONVEX_HULL_CHROMIUM:
2742 case GL_BOUNDING_BOX_CHROMIUM:
2743 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2744 break;
2745 default:
2746 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2747 return false;
2748 }
2749
2750 return true;
2751}
2752
2753bool ValidateStencilFillPathInstanced(Context *context,
2754 GLsizei numPaths,
2755 GLenum pathNameType,
2756 const void *paths,
2757 GLuint pathBase,
2758 GLenum fillMode,
2759 GLuint mask,
2760 GLenum transformType,
2761 const GLfloat *transformValues)
2762{
2763
2764 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2765 transformType, transformValues))
2766 return false;
2767
2768 switch (fillMode)
2769 {
2770 case GL_COUNT_UP_CHROMIUM:
2771 case GL_COUNT_DOWN_CHROMIUM:
2772 break;
2773 default:
2774 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2775 return false;
2776 }
2777 if (!isPow2(mask + 1))
2778 {
2779 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2780 return false;
2781 }
2782 return true;
2783}
2784
2785bool ValidateStencilStrokePathInstanced(Context *context,
2786 GLsizei numPaths,
2787 GLenum pathNameType,
2788 const void *paths,
2789 GLuint pathBase,
2790 GLint reference,
2791 GLuint mask,
2792 GLenum transformType,
2793 const GLfloat *transformValues)
2794{
2795 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2796 transformType, transformValues))
2797 return false;
2798
2799 // no more validation here.
2800
2801 return true;
2802}
2803
2804bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2805 GLsizei numPaths,
2806 GLenum pathNameType,
2807 const void *paths,
2808 GLuint pathBase,
2809 GLenum fillMode,
2810 GLuint mask,
2811 GLenum coverMode,
2812 GLenum transformType,
2813 const GLfloat *transformValues)
2814{
2815 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2816 transformType, transformValues))
2817 return false;
2818
2819 switch (coverMode)
2820 {
2821 case GL_CONVEX_HULL_CHROMIUM:
2822 case GL_BOUNDING_BOX_CHROMIUM:
2823 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2824 break;
2825 default:
2826 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2827 return false;
2828 }
2829
2830 switch (fillMode)
2831 {
2832 case GL_COUNT_UP_CHROMIUM:
2833 case GL_COUNT_DOWN_CHROMIUM:
2834 break;
2835 default:
2836 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2837 return false;
2838 }
2839 if (!isPow2(mask + 1))
2840 {
2841 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2842 return false;
2843 }
2844
2845 return true;
2846}
2847
2848bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2849 GLsizei numPaths,
2850 GLenum pathNameType,
2851 const void *paths,
2852 GLuint pathBase,
2853 GLint reference,
2854 GLuint mask,
2855 GLenum coverMode,
2856 GLenum transformType,
2857 const GLfloat *transformValues)
2858{
2859 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2860 transformType, transformValues))
2861 return false;
2862
2863 switch (coverMode)
2864 {
2865 case GL_CONVEX_HULL_CHROMIUM:
2866 case GL_BOUNDING_BOX_CHROMIUM:
2867 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2868 break;
2869 default:
2870 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2871 return false;
2872 }
2873
2874 return true;
2875}
2876
Jamie Madillc29968b2016-01-20 11:17:23 -05002877} // namespace gl