blob: e329fd006115a5e563401a34af64eef8d749eee5 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/validationES.h"
Jamie Madill73a84962016-02-12 09:27:23 -050014#include "libANGLE/validationES3.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Context.h"
16#include "libANGLE/Texture.h"
17#include "libANGLE/Framebuffer.h"
18#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/formatutils.h"
20#include "libANGLE/FramebufferAttachment.h"
Geoff Langd8605522016-04-13 10:19:12 -040021#include "libANGLE/Uniform.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
23#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030024#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025#include "common/utilities.h"
26
27namespace gl
28{
29
Jamie Madillc29968b2016-01-20 11:17:23 -050030namespace
31{
32
33bool IsPartialBlit(gl::Context *context,
34 const FramebufferAttachment *readBuffer,
35 const FramebufferAttachment *writeBuffer,
36 GLint srcX0,
37 GLint srcY0,
38 GLint srcX1,
39 GLint srcY1,
40 GLint dstX0,
41 GLint dstY0,
42 GLint dstX1,
43 GLint dstY1)
44{
45 const Extents &writeSize = writeBuffer->getSize();
46 const Extents &readSize = readBuffer->getSize();
47
48 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
49 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
50 {
51 return true;
52 }
53
Jamie Madilldfde6ab2016-06-09 07:07:18 -070054 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050055 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050057 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
58 scissor.height < writeSize.height;
59 }
60
61 return false;
62}
63
Sami Väisänend59ca052016-06-21 16:10:00 +030064template <typename T>
65bool ValidatePathInstances(gl::Context *context,
66 GLsizei numPaths,
67 const void *paths,
68 GLuint pathBase)
69{
70 const auto *array = static_cast<const T *>(paths);
71
72 for (GLsizei i = 0; i < numPaths; ++i)
73 {
74 const GLuint pathName = array[i] + pathBase;
75 if (context->hasPath(pathName) && !context->hasPathData(pathName))
76 {
77 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
78 return false;
79 }
80 }
81 return true;
82}
83
84bool ValidateInstancedPathParameters(gl::Context *context,
85 GLsizei numPaths,
86 GLenum pathNameType,
87 const void *paths,
88 GLuint pathBase,
89 GLenum transformType,
90 const GLfloat *transformValues)
91{
92 if (!context->getExtensions().pathRendering)
93 {
94 context->handleError(
95 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
96 return false;
97 }
98
99 if (paths == nullptr)
100 {
101 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
102 return false;
103 }
104
105 if (numPaths < 0)
106 {
107 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
108 return false;
109 }
110
111 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
112 {
113 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
114 return false;
115 }
116
117 std::uint32_t pathNameTypeSize = 0;
118 std::uint32_t componentCount = 0;
119
120 switch (pathNameType)
121 {
122 case GL_UNSIGNED_BYTE:
123 pathNameTypeSize = sizeof(GLubyte);
124 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
125 return false;
126 break;
127
128 case GL_BYTE:
129 pathNameTypeSize = sizeof(GLbyte);
130 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
131 return false;
132 break;
133
134 case GL_UNSIGNED_SHORT:
135 pathNameTypeSize = sizeof(GLushort);
136 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
137 return false;
138 break;
139
140 case GL_SHORT:
141 pathNameTypeSize = sizeof(GLshort);
142 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
143 return false;
144 break;
145
146 case GL_UNSIGNED_INT:
147 pathNameTypeSize = sizeof(GLuint);
148 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
149 return false;
150 break;
151
152 case GL_INT:
153 pathNameTypeSize = sizeof(GLint);
154 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
155 return false;
156 break;
157
158 default:
159 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
160 return false;
161 }
162
163 switch (transformType)
164 {
165 case GL_NONE:
166 componentCount = 0;
167 break;
168 case GL_TRANSLATE_X_CHROMIUM:
169 case GL_TRANSLATE_Y_CHROMIUM:
170 componentCount = 1;
171 break;
172 case GL_TRANSLATE_2D_CHROMIUM:
173 componentCount = 2;
174 break;
175 case GL_TRANSLATE_3D_CHROMIUM:
176 componentCount = 3;
177 break;
178 case GL_AFFINE_2D_CHROMIUM:
179 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
180 componentCount = 6;
181 break;
182 case GL_AFFINE_3D_CHROMIUM:
183 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
184 componentCount = 12;
185 break;
186 default:
187 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
188 return false;
189 }
190 if (componentCount != 0 && transformValues == nullptr)
191 {
192 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
193 return false;
194 }
195
196 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
197 checkedSize += (numPaths * pathNameTypeSize);
198 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
199 if (!checkedSize.IsValid())
200 {
201 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
202 return false;
203 }
204
205 return true;
206}
207
Geoff Lang97073d12016-04-20 10:42:34 -0700208bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
209{
210 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
211 switch (internalFormatInfo.format)
212 {
213 case GL_ALPHA:
214 case GL_LUMINANCE:
215 case GL_LUMINANCE_ALPHA:
216 case GL_RGB:
217 case GL_RGBA:
218 return true;
219
220 case GL_RED:
221 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
222
223 case GL_BGRA_EXT:
224 return context->getExtensions().textureFormatBGRA8888;
225
226 default:
227 return false;
228 }
229}
230
231bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
232{
233 switch (internalFormat)
234 {
235 case GL_RGB:
236 case GL_RGBA:
237 break;
238
239 case GL_BGRA_EXT:
240 return context->getExtensions().textureFormatBGRA8888;
241
242 default:
243 return false;
244 }
245
246 switch (type)
247 {
248 case GL_UNSIGNED_BYTE:
249 break;
250
251 default:
252 return false;
253 }
254
255 return true;
256}
257
258bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
259{
260 switch (target)
261 {
262 case GL_TEXTURE_2D:
263 return true;
264
265 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
266 // supported
267
268 default:
269 return false;
270 }
271}
272
273bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
274{
275 if (IsValidCopyTextureDestinationTarget(context, target))
276 {
277 return true;
278 }
279
280 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
281 // supported
282
283 return false;
284}
285
Jamie Madillc29968b2016-01-20 11:17:23 -0500286} // anonymous namespace
287
Geoff Langb1196682014-07-23 13:47:29 -0400288bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400289 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
290 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
291{
Jamie Madill6f38f822014-06-06 17:12:20 -0400292 if (!ValidTexture2DDestinationTarget(context, target))
293 {
Jamie Madill437fa652016-05-03 15:13:24 -0400294 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400295 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400296 }
297
Austin Kinross08528e12015-10-07 16:24:40 -0700298 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400299 {
Jamie Madill437fa652016-05-03 15:13:24 -0400300 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400301 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400302 }
303
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304 if (level < 0 || xoffset < 0 ||
305 std::numeric_limits<GLsizei>::max() - xoffset < width ||
306 std::numeric_limits<GLsizei>::max() - yoffset < height)
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 Lang005df412013-10-16 14:12:50 -0400312 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400313 {
Jamie Madill437fa652016-05-03 15:13:24 -0400314 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400315 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 }
317
Geoff Langaae65a42014-05-26 12:43:44 -0400318 const gl::Caps &caps = context->getCaps();
319
Geoff Langa9be0dc2014-12-17 12:34:40 -0500320 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400321 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500322 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
323 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400324 {
Jamie Madill437fa652016-05-03 15:13:24 -0400325 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500328 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500329 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500330 {
331 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332 {
Jamie Madill437fa652016-05-03 15:13:24 -0400333 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336
Geoff Langa9be0dc2014-12-17 12:34:40 -0500337 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
338 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
339 {
Jamie Madill437fa652016-05-03 15:13:24 -0400340 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500341 return false;
342 }
343 }
344 else
345 {
Jamie Madill437fa652016-05-03 15:13:24 -0400346 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400347 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348 }
349
Geoff Lang691e58c2014-12-19 17:03:25 -0500350 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400351 if (!texture)
352 {
Jamie Madill437fa652016-05-03 15:13:24 -0400353 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400354 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400355 }
356
Geoff Langa9be0dc2014-12-17 12:34:40 -0500357 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400358 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500359 if (format != GL_NONE)
360 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400361 if (gl::GetSizedInternalFormat(format, type) !=
362 texture->getFormat(target, level).asSized())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500363 {
Jamie Madill437fa652016-05-03 15:13:24 -0400364 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500365 return false;
366 }
367 }
368
369 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
370 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
371 {
Jamie Madill437fa652016-05-03 15:13:24 -0400372 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500373 return false;
374 }
375 }
376 else
377 {
Geoff Lang69cce582015-09-17 13:20:36 -0400378 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500379 {
Jamie Madill437fa652016-05-03 15:13:24 -0400380 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500381 return false;
382 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 }
384
385 // Verify zero border
386 if (border != 0)
387 {
Jamie Madill437fa652016-05-03 15:13:24 -0400388 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400389 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400390 }
391
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400392 if (isCompressed)
393 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400394 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400395 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 switch (actualInternalFormat)
397 {
398 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
399 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400400 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 {
Jamie Madill437fa652016-05-03 15:13:24 -0400402 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400404 }
405 break;
406 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400407 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -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 Lange8ebe7f2013-08-05 15:03:13 -0400411 }
412 break;
413 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400414 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400415 {
Jamie Madill437fa652016-05-03 15:13:24 -0400416 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400417 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400418 }
419 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400420 case GL_ETC1_RGB8_OES:
421 if (!context->getExtensions().compressedETC1RGB8Texture)
422 {
Jamie Madill437fa652016-05-03 15:13:24 -0400423 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400424 return false;
425 }
426 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800427 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
428 if (!context->getExtensions().lossyETCDecode)
429 {
Jamie Madill437fa652016-05-03 15:13:24 -0400430 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800431 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
432 return false;
433 }
434 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400435 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400436 context->handleError(Error(
tmartino0ccd5ae2015-10-01 14:33:14 -0400437 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
438 return false;
439 }
440 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
441 {
Jamie Madill437fa652016-05-03 15:13:24 -0400442 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400443 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400444 }
445 }
446 else
447 {
448 // validate <type> by itself (used as secondary key below)
449 switch (type)
450 {
451 case GL_UNSIGNED_BYTE:
452 case GL_UNSIGNED_SHORT_5_6_5:
453 case GL_UNSIGNED_SHORT_4_4_4_4:
454 case GL_UNSIGNED_SHORT_5_5_5_1:
455 case GL_UNSIGNED_SHORT:
456 case GL_UNSIGNED_INT:
457 case GL_UNSIGNED_INT_24_8_OES:
458 case GL_HALF_FLOAT_OES:
459 case GL_FLOAT:
460 break;
461 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400462 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400463 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400464 }
465
466 // validate <format> + <type> combinations
467 // - invalid <format> -> sets INVALID_ENUM
468 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
469 switch (format)
470 {
471 case GL_ALPHA:
472 case GL_LUMINANCE:
473 case GL_LUMINANCE_ALPHA:
474 switch (type)
475 {
476 case GL_UNSIGNED_BYTE:
477 case GL_FLOAT:
478 case GL_HALF_FLOAT_OES:
479 break;
Geoff Langb1196682014-07-23 13:47:29 -0400480 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400481 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400482 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400483 }
484 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400485 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400486 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400487 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400488 {
Jamie Madill437fa652016-05-03 15:13:24 -0400489 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400490 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400491 }
492 switch (type)
493 {
494 case GL_UNSIGNED_BYTE:
495 case GL_FLOAT:
496 case GL_HALF_FLOAT_OES:
497 break;
498 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400499 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400500 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400501 }
502 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400503 case GL_RGB:
504 switch (type)
505 {
506 case GL_UNSIGNED_BYTE:
507 case GL_UNSIGNED_SHORT_5_6_5:
508 case GL_FLOAT:
509 case GL_HALF_FLOAT_OES:
510 break;
511 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400512 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400513 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400514 }
515 break;
516 case GL_RGBA:
517 switch (type)
518 {
519 case GL_UNSIGNED_BYTE:
520 case GL_UNSIGNED_SHORT_4_4_4_4:
521 case GL_UNSIGNED_SHORT_5_5_5_1:
522 case GL_FLOAT:
523 case GL_HALF_FLOAT_OES:
524 break;
525 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400526 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400527 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400528 }
529 break;
530 case GL_BGRA_EXT:
531 switch (type)
532 {
533 case GL_UNSIGNED_BYTE:
534 break;
535 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400536 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400538 }
539 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400540 case GL_SRGB_EXT:
541 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400542 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400543 {
Jamie Madill437fa652016-05-03 15:13:24 -0400544 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400545 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400546 }
547 switch (type)
548 {
549 case GL_UNSIGNED_BYTE:
550 break;
551 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400552 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400553 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400554 }
555 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400556 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
557 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
558 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
559 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
560 break;
561 case GL_DEPTH_COMPONENT:
562 switch (type)
563 {
564 case GL_UNSIGNED_SHORT:
565 case GL_UNSIGNED_INT:
566 break;
567 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400568 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400569 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400570 }
571 break;
572 case GL_DEPTH_STENCIL_OES:
573 switch (type)
574 {
575 case GL_UNSIGNED_INT_24_8_OES:
576 break;
577 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400578 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400579 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400580 }
581 break;
582 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400583 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400584 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400585 }
586
587 switch (format)
588 {
589 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
590 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400591 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400592 {
Jamie Madill437fa652016-05-03 15:13:24 -0400593 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400594 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400595 }
596 else
597 {
Jamie Madill437fa652016-05-03 15:13:24 -0400598 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400599 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400600 }
601 break;
602 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400603 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400604 {
Jamie Madill437fa652016-05-03 15:13:24 -0400605 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400606 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400607 }
608 else
609 {
Jamie Madill437fa652016-05-03 15:13:24 -0400610 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400612 }
613 break;
614 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400615 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400616 {
Jamie Madill437fa652016-05-03 15:13:24 -0400617 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400618 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400619 }
620 else
621 {
Jamie Madill437fa652016-05-03 15:13:24 -0400622 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400623 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624 }
625 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400626 case GL_ETC1_RGB8_OES:
627 if (context->getExtensions().compressedETC1RGB8Texture)
628 {
Jamie Madill437fa652016-05-03 15:13:24 -0400629 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400630 return false;
631 }
632 else
633 {
Jamie Madill437fa652016-05-03 15:13:24 -0400634 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400635 return false;
636 }
637 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800638 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
639 if (context->getExtensions().lossyETCDecode)
640 {
Jamie Madill437fa652016-05-03 15:13:24 -0400641 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800642 Error(GL_INVALID_OPERATION,
643 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
644 return false;
645 }
646 else
647 {
Jamie Madill437fa652016-05-03 15:13:24 -0400648 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800649 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
650 return false;
651 }
652 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400653 case GL_DEPTH_COMPONENT:
654 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400655 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656 {
Jamie Madill437fa652016-05-03 15:13:24 -0400657 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400658 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400659 }
660 if (target != GL_TEXTURE_2D)
661 {
Jamie Madill437fa652016-05-03 15:13:24 -0400662 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400663 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400664 }
665 // OES_depth_texture supports loading depth data and multiple levels,
666 // but ANGLE_depth_texture does not
667 if (pixels != NULL || level != 0)
668 {
Jamie Madill437fa652016-05-03 15:13:24 -0400669 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400670 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400671 }
672 break;
673 default:
674 break;
675 }
676
677 if (type == GL_FLOAT)
678 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400679 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400680 {
Jamie Madill437fa652016-05-03 15:13:24 -0400681 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400682 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400683 }
684 }
685 else if (type == GL_HALF_FLOAT_OES)
686 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400687 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400688 {
Jamie Madill437fa652016-05-03 15:13:24 -0400689 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400690 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400691 }
692 }
693 }
694
695 return true;
696}
697
Jamie Madillc29968b2016-01-20 11:17:23 -0500698bool ValidateES2CopyTexImageParameters(ValidationContext *context,
699 GLenum target,
700 GLint level,
701 GLenum internalformat,
702 bool isSubImage,
703 GLint xoffset,
704 GLint yoffset,
705 GLint x,
706 GLint y,
707 GLsizei width,
708 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400709 GLint border)
710{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500711 if (!ValidTexture2DDestinationTarget(context, target))
712 {
Jamie Madill437fa652016-05-03 15:13:24 -0400713 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500714 return false;
715 }
716
Jamie Madill0c8abca2016-07-22 20:21:26 -0400717 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400718 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400719 xoffset, yoffset, 0, x, y, width, height, border,
720 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400721 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400722 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400723 }
724
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700725 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400726 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400727 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400728
729 // [OpenGL ES 2.0.24] table 3.9
730 if (isSubImage)
731 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400732 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 {
734 case GL_ALPHA:
735 if (colorbufferFormat != GL_ALPHA8_EXT &&
736 colorbufferFormat != GL_RGBA4 &&
737 colorbufferFormat != GL_RGB5_A1 &&
738 colorbufferFormat != GL_RGBA8_OES)
739 {
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 }
743 break;
744 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400745 if (colorbufferFormat != GL_R8_EXT &&
746 colorbufferFormat != GL_RG8_EXT &&
747 colorbufferFormat != GL_RGB565 &&
748 colorbufferFormat != GL_RGB8_OES &&
749 colorbufferFormat != GL_RGBA4 &&
750 colorbufferFormat != GL_RGB5_A1 &&
751 colorbufferFormat != GL_RGBA8_OES)
752 {
Jamie Madill437fa652016-05-03 15:13:24 -0400753 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400754 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400755 }
756 break;
757 case GL_RED_EXT:
758 if (colorbufferFormat != GL_R8_EXT &&
759 colorbufferFormat != GL_RG8_EXT &&
760 colorbufferFormat != GL_RGB565 &&
761 colorbufferFormat != GL_RGB8_OES &&
762 colorbufferFormat != GL_RGBA4 &&
763 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500764 colorbufferFormat != GL_RGBA8_OES &&
765 colorbufferFormat != GL_R32F &&
766 colorbufferFormat != GL_RG32F &&
767 colorbufferFormat != GL_RGB32F &&
768 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -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 Lang632192d2013-10-04 13:40:46 -0400772 }
773 break;
774 case GL_RG_EXT:
775 if (colorbufferFormat != GL_RG8_EXT &&
776 colorbufferFormat != GL_RGB565 &&
777 colorbufferFormat != GL_RGB8_OES &&
778 colorbufferFormat != GL_RGBA4 &&
779 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500780 colorbufferFormat != GL_RGBA8_OES &&
781 colorbufferFormat != GL_RG32F &&
782 colorbufferFormat != GL_RGB32F &&
783 colorbufferFormat != GL_RGBA32F)
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;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 case GL_RGB:
790 if (colorbufferFormat != GL_RGB565 &&
791 colorbufferFormat != GL_RGB8_OES &&
792 colorbufferFormat != GL_RGBA4 &&
793 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500794 colorbufferFormat != GL_RGBA8_OES &&
795 colorbufferFormat != GL_RGB32F &&
796 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797 {
Jamie Madill437fa652016-05-03 15:13:24 -0400798 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400799 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400800 }
801 break;
802 case GL_LUMINANCE_ALPHA:
803 case GL_RGBA:
804 if (colorbufferFormat != GL_RGBA4 &&
805 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500806 colorbufferFormat != GL_RGBA8_OES &&
807 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808 {
Jamie Madill437fa652016-05-03 15:13:24 -0400809 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400810 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 }
812 break;
813 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
814 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
815 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
816 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400817 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800818 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400819 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400820 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 case GL_DEPTH_COMPONENT:
822 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400823 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400824 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400826 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500829
Jamie Madill0c8abca2016-07-22 20:21:26 -0400830 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500831 {
Jamie Madill437fa652016-05-03 15:13:24 -0400832 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500833 return false;
834 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 }
836 else
837 {
838 switch (internalformat)
839 {
840 case GL_ALPHA:
841 if (colorbufferFormat != GL_ALPHA8_EXT &&
842 colorbufferFormat != GL_RGBA4 &&
843 colorbufferFormat != GL_RGB5_A1 &&
844 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500845 colorbufferFormat != GL_RGBA8_OES &&
846 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851 break;
852 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400853 if (colorbufferFormat != GL_R8_EXT &&
854 colorbufferFormat != GL_RG8_EXT &&
855 colorbufferFormat != GL_RGB565 &&
856 colorbufferFormat != GL_RGB8_OES &&
857 colorbufferFormat != GL_RGBA4 &&
858 colorbufferFormat != GL_RGB5_A1 &&
859 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500860 colorbufferFormat != GL_RGBA8_OES &&
861 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400862 {
Jamie Madill437fa652016-05-03 15:13:24 -0400863 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400864 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400865 }
866 break;
867 case GL_RED_EXT:
868 if (colorbufferFormat != GL_R8_EXT &&
869 colorbufferFormat != GL_RG8_EXT &&
870 colorbufferFormat != GL_RGB565 &&
871 colorbufferFormat != GL_RGB8_OES &&
872 colorbufferFormat != GL_RGBA4 &&
873 colorbufferFormat != GL_RGB5_A1 &&
874 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500875 colorbufferFormat != GL_RGBA8_OES &&
876 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400877 {
Jamie Madill437fa652016-05-03 15:13:24 -0400878 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400879 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400880 }
881 break;
882 case GL_RG_EXT:
883 if (colorbufferFormat != GL_RG8_EXT &&
884 colorbufferFormat != GL_RGB565 &&
885 colorbufferFormat != GL_RGB8_OES &&
886 colorbufferFormat != GL_RGBA4 &&
887 colorbufferFormat != GL_RGB5_A1 &&
888 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500889 colorbufferFormat != GL_RGBA8_OES &&
890 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400891 {
Jamie Madill437fa652016-05-03 15:13:24 -0400892 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400893 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400894 }
895 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400896 case GL_RGB:
897 if (colorbufferFormat != GL_RGB565 &&
898 colorbufferFormat != GL_RGB8_OES &&
899 colorbufferFormat != GL_RGBA4 &&
900 colorbufferFormat != GL_RGB5_A1 &&
901 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500902 colorbufferFormat != GL_RGBA8_OES &&
903 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400904 {
Jamie Madill437fa652016-05-03 15:13:24 -0400905 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400906 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 }
908 break;
909 case GL_LUMINANCE_ALPHA:
910 case GL_RGBA:
911 if (colorbufferFormat != GL_RGBA4 &&
912 colorbufferFormat != GL_RGB5_A1 &&
913 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500914 colorbufferFormat != GL_RGBA8_OES &&
915 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400916 {
Jamie Madill437fa652016-05-03 15:13:24 -0400917 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400918 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919 }
920 break;
921 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
922 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400923 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 {
Jamie Madill437fa652016-05-03 15:13:24 -0400925 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400926 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927 }
928 else
929 {
Jamie Madill437fa652016-05-03 15:13:24 -0400930 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400931 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 }
933 break;
934 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400935 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400936 {
Jamie Madill437fa652016-05-03 15:13:24 -0400937 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939 }
940 else
941 {
Jamie Madill437fa652016-05-03 15:13:24 -0400942 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944 }
945 break;
946 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400947 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 {
Jamie Madill437fa652016-05-03 15:13:24 -0400949 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 }
952 else
953 {
Jamie Madill437fa652016-05-03 15:13:24 -0400954 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 }
957 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400958 case GL_ETC1_RGB8_OES:
959 if (context->getExtensions().compressedETC1RGB8Texture)
960 {
Jamie Madill437fa652016-05-03 15:13:24 -0400961 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400962 return false;
963 }
964 else
965 {
Jamie Madill437fa652016-05-03 15:13:24 -0400966 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400967 return false;
968 }
969 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800970 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
971 if (context->getExtensions().lossyETCDecode)
972 {
Jamie Madill437fa652016-05-03 15:13:24 -0400973 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gonge3939b92015-12-01 15:36:51 -0800974 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
975 return false;
976 }
977 else
978 {
Jamie Madill437fa652016-05-03 15:13:24 -0400979 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800980 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
981 return false;
982 }
983 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400984 case GL_DEPTH_COMPONENT:
985 case GL_DEPTH_COMPONENT16:
986 case GL_DEPTH_COMPONENT32_OES:
987 case GL_DEPTH_STENCIL_OES:
988 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400989 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400990 {
Jamie Madill437fa652016-05-03 15:13:24 -0400991 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400992 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 }
994 else
995 {
Jamie Madill437fa652016-05-03 15:13:24 -0400996 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400997 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400998 }
999 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001000 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003 }
1004
Geoff Lang784a8fd2013-09-24 12:33:16 -04001005 // If width or height is zero, it is a no-op. Return false without setting an error.
1006 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007}
1008
Geoff Langb1196682014-07-23 13:47:29 -04001009bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 GLsizei width, GLsizei height)
1011{
1012 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1013 {
Jamie Madill437fa652016-05-03 15:13:24 -04001014 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001015 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 }
1017
1018 if (width < 1 || height < 1 || levels < 1)
1019 {
Jamie Madill437fa652016-05-03 15:13:24 -04001020 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001021 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001022 }
1023
1024 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1025 {
Jamie Madill437fa652016-05-03 15:13:24 -04001026 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001027 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 }
1029
1030 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1031 {
Jamie Madill437fa652016-05-03 15:13:24 -04001032 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001033 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034 }
1035
Geoff Lang5d601382014-07-22 15:14:06 -04001036 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1037 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 {
Jamie Madill437fa652016-05-03 15:13:24 -04001039 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 }
1042
Geoff Langaae65a42014-05-26 12:43:44 -04001043 const gl::Caps &caps = context->getCaps();
1044
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 switch (target)
1046 {
1047 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -04001048 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1049 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001052 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 }
1054 break;
1055 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -04001056 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1057 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 {
Jamie Madill437fa652016-05-03 15:13:24 -04001059 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001060 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001061 }
1062 break;
1063 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001064 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001065 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001066 }
1067
Geoff Langc0b9ef42014-07-02 10:02:37 -04001068 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069 {
1070 if (!gl::isPow2(width) || !gl::isPow2(height))
1071 {
Jamie Madill437fa652016-05-03 15:13:24 -04001072 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001073 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 }
1075 }
1076
1077 switch (internalformat)
1078 {
1079 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1080 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001081 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 {
Jamie Madill437fa652016-05-03 15:13:24 -04001083 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 }
1086 break;
1087 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001088 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 {
Jamie Madill437fa652016-05-03 15:13:24 -04001090 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093 break;
1094 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001095 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096 {
Jamie Madill437fa652016-05-03 15:13:24 -04001097 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001098 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 }
1100 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -04001101 case GL_ETC1_RGB8_OES:
1102 if (!context->getExtensions().compressedETC1RGB8Texture)
1103 {
Jamie Madill437fa652016-05-03 15:13:24 -04001104 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -04001105 return false;
1106 }
1107 break;
Minmin Gonge3939b92015-12-01 15:36:51 -08001108 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1109 if (!context->getExtensions().lossyETCDecode)
1110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001112 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1113 return false;
1114 }
1115 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116 case GL_RGBA32F_EXT:
1117 case GL_RGB32F_EXT:
1118 case GL_ALPHA32F_EXT:
1119 case GL_LUMINANCE32F_EXT:
1120 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001121 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001122 {
Jamie Madill437fa652016-05-03 15:13:24 -04001123 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125 }
1126 break;
1127 case GL_RGBA16F_EXT:
1128 case GL_RGB16F_EXT:
1129 case GL_ALPHA16F_EXT:
1130 case GL_LUMINANCE16F_EXT:
1131 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001132 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 {
Jamie Madill437fa652016-05-03 15:13:24 -04001134 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136 }
1137 break;
Geoff Lang632192d2013-10-04 13:40:46 -04001138 case GL_R8_EXT:
1139 case GL_RG8_EXT:
1140 case GL_R16F_EXT:
1141 case GL_RG16F_EXT:
1142 case GL_R32F_EXT:
1143 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001144 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -04001145 {
Jamie Madill437fa652016-05-03 15:13:24 -04001146 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Geoff Lang632192d2013-10-04 13:40:46 -04001148 }
1149 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 case GL_DEPTH_COMPONENT16:
1151 case GL_DEPTH_COMPONENT32_OES:
1152 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001153 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 {
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158 if (target != GL_TEXTURE_2D)
1159 {
Jamie Madill437fa652016-05-03 15:13:24 -04001160 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001161 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001162 }
1163 // ANGLE_depth_texture only supports 1-level textures
1164 if (levels != 1)
1165 {
Jamie Madill437fa652016-05-03 15:13:24 -04001166 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001167 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 }
1169 break;
1170 default:
1171 break;
1172 }
1173
Geoff Lang691e58c2014-12-19 17:03:25 -05001174 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001175 if (!texture || texture->id() == 0)
1176 {
Jamie Madill437fa652016-05-03 15:13:24 -04001177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 }
1180
Geoff Lang69cce582015-09-17 13:20:36 -04001181 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 {
Jamie Madill437fa652016-05-03 15:13:24 -04001183 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001184 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001185 }
1186
1187 return true;
1188}
1189
Austin Kinross08332632015-05-05 13:35:47 -07001190bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1191 const GLenum *attachments)
1192{
Jamie Madillc29968b2016-01-20 11:17:23 -05001193 if (!context->getExtensions().discardFramebuffer)
1194 {
Jamie Madill437fa652016-05-03 15:13:24 -04001195 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001196 return false;
1197 }
1198
Austin Kinross08332632015-05-05 13:35:47 -07001199 bool defaultFramebuffer = false;
1200
1201 switch (target)
1202 {
1203 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001204 defaultFramebuffer =
1205 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1206 break;
Austin Kinross08332632015-05-05 13:35:47 -07001207 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001208 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001209 return false;
1210 }
1211
1212 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1213}
1214
Austin Kinrossbc781f32015-10-26 09:27:38 -07001215bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1216{
1217 if (!context->getExtensions().vertexArrayObject)
1218 {
Jamie Madill437fa652016-05-03 15:13:24 -04001219 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001220 return false;
1221 }
1222
1223 return ValidateBindVertexArrayBase(context, array);
1224}
1225
1226bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1227{
1228 if (!context->getExtensions().vertexArrayObject)
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001231 return false;
1232 }
1233
Olli Etuaho41997e72016-03-10 13:38:39 +02001234 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001235}
1236
1237bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1238{
1239 if (!context->getExtensions().vertexArrayObject)
1240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001242 return false;
1243 }
1244
Olli Etuaho41997e72016-03-10 13:38:39 +02001245 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001246}
1247
1248bool ValidateIsVertexArrayOES(Context *context)
1249{
1250 if (!context->getExtensions().vertexArrayObject)
1251 {
Jamie Madill437fa652016-05-03 15:13:24 -04001252 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001253 return false;
1254 }
1255
1256 return true;
1257}
Geoff Langc5629752015-12-07 16:29:04 -05001258
1259bool ValidateProgramBinaryOES(Context *context,
1260 GLuint program,
1261 GLenum binaryFormat,
1262 const void *binary,
1263 GLint length)
1264{
1265 if (!context->getExtensions().getProgramBinary)
1266 {
Jamie Madill437fa652016-05-03 15:13:24 -04001267 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001268 return false;
1269 }
1270
1271 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1272}
1273
1274bool ValidateGetProgramBinaryOES(Context *context,
1275 GLuint program,
1276 GLsizei bufSize,
1277 GLsizei *length,
1278 GLenum *binaryFormat,
1279 void *binary)
1280{
1281 if (!context->getExtensions().getProgramBinary)
1282 {
Jamie Madill437fa652016-05-03 15:13:24 -04001283 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001284 return false;
1285 }
1286
1287 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1288}
Geoff Lange102fee2015-12-10 11:23:30 -05001289
Geoff Lang70d0f492015-12-10 17:45:46 -05001290static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1291{
1292 switch (source)
1293 {
1294 case GL_DEBUG_SOURCE_API:
1295 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1296 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1297 case GL_DEBUG_SOURCE_OTHER:
1298 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1299 return !mustBeThirdPartyOrApplication;
1300
1301 case GL_DEBUG_SOURCE_THIRD_PARTY:
1302 case GL_DEBUG_SOURCE_APPLICATION:
1303 return true;
1304
1305 default:
1306 return false;
1307 }
1308}
1309
1310static bool ValidDebugType(GLenum type)
1311{
1312 switch (type)
1313 {
1314 case GL_DEBUG_TYPE_ERROR:
1315 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1316 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1317 case GL_DEBUG_TYPE_PERFORMANCE:
1318 case GL_DEBUG_TYPE_PORTABILITY:
1319 case GL_DEBUG_TYPE_OTHER:
1320 case GL_DEBUG_TYPE_MARKER:
1321 case GL_DEBUG_TYPE_PUSH_GROUP:
1322 case GL_DEBUG_TYPE_POP_GROUP:
1323 return true;
1324
1325 default:
1326 return false;
1327 }
1328}
1329
1330static bool ValidDebugSeverity(GLenum severity)
1331{
1332 switch (severity)
1333 {
1334 case GL_DEBUG_SEVERITY_HIGH:
1335 case GL_DEBUG_SEVERITY_MEDIUM:
1336 case GL_DEBUG_SEVERITY_LOW:
1337 case GL_DEBUG_SEVERITY_NOTIFICATION:
1338 return true;
1339
1340 default:
1341 return false;
1342 }
1343}
1344
Geoff Lange102fee2015-12-10 11:23:30 -05001345bool ValidateDebugMessageControlKHR(Context *context,
1346 GLenum source,
1347 GLenum type,
1348 GLenum severity,
1349 GLsizei count,
1350 const GLuint *ids,
1351 GLboolean enabled)
1352{
1353 if (!context->getExtensions().debug)
1354 {
Jamie Madill437fa652016-05-03 15:13:24 -04001355 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001356 return false;
1357 }
1358
Geoff Lang70d0f492015-12-10 17:45:46 -05001359 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1360 {
Jamie Madill437fa652016-05-03 15:13:24 -04001361 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001362 return false;
1363 }
1364
1365 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1366 {
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001368 return false;
1369 }
1370
1371 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001374 return false;
1375 }
1376
1377 if (count > 0)
1378 {
1379 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1380 {
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001382 GL_INVALID_OPERATION,
1383 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1384 return false;
1385 }
1386
1387 if (severity != GL_DONT_CARE)
1388 {
Jamie Madill437fa652016-05-03 15:13:24 -04001389 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001390 Error(GL_INVALID_OPERATION,
1391 "If count is greater than zero, severity must be GL_DONT_CARE."));
1392 return false;
1393 }
1394 }
1395
Geoff Lange102fee2015-12-10 11:23:30 -05001396 return true;
1397}
1398
1399bool ValidateDebugMessageInsertKHR(Context *context,
1400 GLenum source,
1401 GLenum type,
1402 GLuint id,
1403 GLenum severity,
1404 GLsizei length,
1405 const GLchar *buf)
1406{
1407 if (!context->getExtensions().debug)
1408 {
Jamie Madill437fa652016-05-03 15:13:24 -04001409 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001410 return false;
1411 }
1412
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001413 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001414 {
1415 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1416 // not generate an error.
1417 return false;
1418 }
1419
1420 if (!ValidDebugSeverity(severity))
1421 {
Jamie Madill437fa652016-05-03 15:13:24 -04001422 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001423 return false;
1424 }
1425
1426 if (!ValidDebugType(type))
1427 {
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001429 return false;
1430 }
1431
1432 if (!ValidDebugSource(source, true))
1433 {
Jamie Madill437fa652016-05-03 15:13:24 -04001434 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001435 return false;
1436 }
1437
1438 size_t messageLength = (length < 0) ? strlen(buf) : length;
1439 if (messageLength > context->getExtensions().maxDebugMessageLength)
1440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001442 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1443 return false;
1444 }
1445
Geoff Lange102fee2015-12-10 11:23:30 -05001446 return true;
1447}
1448
1449bool ValidateDebugMessageCallbackKHR(Context *context,
1450 GLDEBUGPROCKHR callback,
1451 const void *userParam)
1452{
1453 if (!context->getExtensions().debug)
1454 {
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001456 return false;
1457 }
1458
Geoff Lange102fee2015-12-10 11:23:30 -05001459 return true;
1460}
1461
1462bool ValidateGetDebugMessageLogKHR(Context *context,
1463 GLuint count,
1464 GLsizei bufSize,
1465 GLenum *sources,
1466 GLenum *types,
1467 GLuint *ids,
1468 GLenum *severities,
1469 GLsizei *lengths,
1470 GLchar *messageLog)
1471{
1472 if (!context->getExtensions().debug)
1473 {
Jamie Madill437fa652016-05-03 15:13:24 -04001474 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001475 return false;
1476 }
1477
Geoff Lang70d0f492015-12-10 17:45:46 -05001478 if (bufSize < 0 && messageLog != nullptr)
1479 {
Jamie Madill437fa652016-05-03 15:13:24 -04001480 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001481 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1482 return false;
1483 }
1484
Geoff Lange102fee2015-12-10 11:23:30 -05001485 return true;
1486}
1487
1488bool ValidatePushDebugGroupKHR(Context *context,
1489 GLenum source,
1490 GLuint id,
1491 GLsizei length,
1492 const GLchar *message)
1493{
1494 if (!context->getExtensions().debug)
1495 {
Jamie Madill437fa652016-05-03 15:13:24 -04001496 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001497 return false;
1498 }
1499
Geoff Lang70d0f492015-12-10 17:45:46 -05001500 if (!ValidDebugSource(source, true))
1501 {
Jamie Madill437fa652016-05-03 15:13:24 -04001502 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001503 return false;
1504 }
1505
1506 size_t messageLength = (length < 0) ? strlen(message) : length;
1507 if (messageLength > context->getExtensions().maxDebugMessageLength)
1508 {
Jamie Madill437fa652016-05-03 15:13:24 -04001509 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001510 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1511 return false;
1512 }
1513
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001514 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001515 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1516 {
Jamie Madill437fa652016-05-03 15:13:24 -04001517 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001518 Error(GL_STACK_OVERFLOW,
1519 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1520 return false;
1521 }
1522
Geoff Lange102fee2015-12-10 11:23:30 -05001523 return true;
1524}
1525
1526bool ValidatePopDebugGroupKHR(Context *context)
1527{
1528 if (!context->getExtensions().debug)
1529 {
Jamie Madill437fa652016-05-03 15:13:24 -04001530 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001531 return false;
1532 }
1533
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001534 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001535 if (currentStackSize <= 1)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001538 return false;
1539 }
1540
1541 return true;
1542}
1543
1544static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1545{
1546 switch (identifier)
1547 {
1548 case GL_BUFFER:
1549 if (context->getBuffer(name) == nullptr)
1550 {
Jamie Madill437fa652016-05-03 15:13:24 -04001551 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001552 return false;
1553 }
1554 return true;
1555
1556 case GL_SHADER:
1557 if (context->getShader(name) == nullptr)
1558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001560 return false;
1561 }
1562 return true;
1563
1564 case GL_PROGRAM:
1565 if (context->getProgram(name) == nullptr)
1566 {
Jamie Madill437fa652016-05-03 15:13:24 -04001567 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001568 return false;
1569 }
1570 return true;
1571
1572 case GL_VERTEX_ARRAY:
1573 if (context->getVertexArray(name) == nullptr)
1574 {
Jamie Madill437fa652016-05-03 15:13:24 -04001575 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001576 return false;
1577 }
1578 return true;
1579
1580 case GL_QUERY:
1581 if (context->getQuery(name) == nullptr)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001584 return false;
1585 }
1586 return true;
1587
1588 case GL_TRANSFORM_FEEDBACK:
1589 if (context->getTransformFeedback(name) == nullptr)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001592 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1593 return false;
1594 }
1595 return true;
1596
1597 case GL_SAMPLER:
1598 if (context->getSampler(name) == nullptr)
1599 {
Jamie Madill437fa652016-05-03 15:13:24 -04001600 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001601 return false;
1602 }
1603 return true;
1604
1605 case GL_TEXTURE:
1606 if (context->getTexture(name) == nullptr)
1607 {
Jamie Madill437fa652016-05-03 15:13:24 -04001608 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001609 return false;
1610 }
1611 return true;
1612
1613 case GL_RENDERBUFFER:
1614 if (context->getRenderbuffer(name) == nullptr)
1615 {
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001617 return false;
1618 }
1619 return true;
1620
1621 case GL_FRAMEBUFFER:
1622 if (context->getFramebuffer(name) == nullptr)
1623 {
Jamie Madill437fa652016-05-03 15:13:24 -04001624 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001625 return false;
1626 }
1627 return true;
1628
1629 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001630 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001631 return false;
1632 }
Geoff Lange102fee2015-12-10 11:23:30 -05001633}
1634
Martin Radev9d901792016-07-15 15:58:58 +03001635static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1636{
1637 size_t labelLength = 0;
1638
1639 if (length < 0)
1640 {
1641 if (label != nullptr)
1642 {
1643 labelLength = strlen(label);
1644 }
1645 }
1646 else
1647 {
1648 labelLength = static_cast<size_t>(length);
1649 }
1650
1651 if (labelLength > context->getExtensions().maxLabelLength)
1652 {
1653 context->handleError(
1654 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1655 return false;
1656 }
1657
1658 return true;
1659}
1660
Geoff Lange102fee2015-12-10 11:23:30 -05001661bool ValidateObjectLabelKHR(Context *context,
1662 GLenum identifier,
1663 GLuint name,
1664 GLsizei length,
1665 const GLchar *label)
1666{
1667 if (!context->getExtensions().debug)
1668 {
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001670 return false;
1671 }
1672
Geoff Lang70d0f492015-12-10 17:45:46 -05001673 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1674 {
1675 return false;
1676 }
1677
Martin Radev9d901792016-07-15 15:58:58 +03001678 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001679 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001680 return false;
1681 }
1682
Geoff Lange102fee2015-12-10 11:23:30 -05001683 return true;
1684}
1685
1686bool ValidateGetObjectLabelKHR(Context *context,
1687 GLenum identifier,
1688 GLuint name,
1689 GLsizei bufSize,
1690 GLsizei *length,
1691 GLchar *label)
1692{
1693 if (!context->getExtensions().debug)
1694 {
Jamie Madill437fa652016-05-03 15:13:24 -04001695 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001696 return false;
1697 }
1698
Geoff Lang70d0f492015-12-10 17:45:46 -05001699 if (bufSize < 0)
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001702 return false;
1703 }
1704
1705 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1706 {
1707 return false;
1708 }
1709
Martin Radev9d901792016-07-15 15:58:58 +03001710 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001711}
1712
1713static bool ValidateObjectPtrName(Context *context, const void *ptr)
1714{
1715 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1716 {
Jamie Madill437fa652016-05-03 15:13:24 -04001717 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001718 return false;
1719 }
1720
Geoff Lange102fee2015-12-10 11:23:30 -05001721 return true;
1722}
1723
1724bool ValidateObjectPtrLabelKHR(Context *context,
1725 const void *ptr,
1726 GLsizei length,
1727 const GLchar *label)
1728{
1729 if (!context->getExtensions().debug)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001732 return false;
1733 }
1734
Geoff Lang70d0f492015-12-10 17:45:46 -05001735 if (!ValidateObjectPtrName(context, ptr))
1736 {
1737 return false;
1738 }
1739
Martin Radev9d901792016-07-15 15:58:58 +03001740 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001741 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001742 return false;
1743 }
1744
Geoff Lange102fee2015-12-10 11:23:30 -05001745 return true;
1746}
1747
1748bool ValidateGetObjectPtrLabelKHR(Context *context,
1749 const void *ptr,
1750 GLsizei bufSize,
1751 GLsizei *length,
1752 GLchar *label)
1753{
1754 if (!context->getExtensions().debug)
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001757 return false;
1758 }
1759
Geoff Lang70d0f492015-12-10 17:45:46 -05001760 if (bufSize < 0)
1761 {
Jamie Madill437fa652016-05-03 15:13:24 -04001762 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001763 return false;
1764 }
1765
1766 if (!ValidateObjectPtrName(context, ptr))
1767 {
1768 return false;
1769 }
1770
Martin Radev9d901792016-07-15 15:58:58 +03001771 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001772}
1773
1774bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1775{
1776 if (!context->getExtensions().debug)
1777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001779 return false;
1780 }
1781
Geoff Lang70d0f492015-12-10 17:45:46 -05001782 // TODO: represent this in Context::getQueryParameterInfo.
1783 switch (pname)
1784 {
1785 case GL_DEBUG_CALLBACK_FUNCTION:
1786 case GL_DEBUG_CALLBACK_USER_PARAM:
1787 break;
1788
1789 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001790 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001791 return false;
1792 }
1793
Geoff Lange102fee2015-12-10 11:23:30 -05001794 return true;
1795}
Jamie Madillc29968b2016-01-20 11:17:23 -05001796
1797bool ValidateBlitFramebufferANGLE(Context *context,
1798 GLint srcX0,
1799 GLint srcY0,
1800 GLint srcX1,
1801 GLint srcY1,
1802 GLint dstX0,
1803 GLint dstY0,
1804 GLint dstX1,
1805 GLint dstY1,
1806 GLbitfield mask,
1807 GLenum filter)
1808{
1809 if (!context->getExtensions().framebufferBlit)
1810 {
Jamie Madill437fa652016-05-03 15:13:24 -04001811 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 return false;
1813 }
1814
1815 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1816 {
1817 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001818 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001819 GL_INVALID_OPERATION,
1820 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1821 return false;
1822 }
1823
1824 if (filter == GL_LINEAR)
1825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001827 return false;
1828 }
1829
Jamie Madill51f40ec2016-06-15 14:06:00 -04001830 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1831 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001832
1833 if (mask & GL_COLOR_BUFFER_BIT)
1834 {
1835 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1836 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1837
1838 if (readColorAttachment && drawColorAttachment)
1839 {
1840 if (!(readColorAttachment->type() == GL_TEXTURE &&
1841 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1842 readColorAttachment->type() != GL_RENDERBUFFER &&
1843 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1844 {
Jamie Madill437fa652016-05-03 15:13:24 -04001845 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001846 return false;
1847 }
1848
Geoff Langa15472a2015-08-11 11:48:03 -04001849 for (size_t drawbufferIdx = 0;
1850 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001851 {
Geoff Langa15472a2015-08-11 11:48:03 -04001852 const FramebufferAttachment *attachment =
1853 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1854 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001855 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 if (!(attachment->type() == GL_TEXTURE &&
1857 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1858 attachment->type() != GL_RENDERBUFFER &&
1859 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001862 return false;
1863 }
1864
1865 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001866 if (!Format::SameSized(attachment->getFormat(),
1867 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001870 return false;
1871 }
1872 }
1873 }
1874
Jamie Madill51f40ec2016-06-15 14:06:00 -04001875 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1877 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882 }
1883 }
1884
1885 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1886 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1887 for (size_t i = 0; i < 2; i++)
1888 {
1889 if (mask & masks[i])
1890 {
1891 const FramebufferAttachment *readBuffer =
1892 readFramebuffer->getAttachment(attachments[i]);
1893 const FramebufferAttachment *drawBuffer =
1894 drawFramebuffer->getAttachment(attachments[i]);
1895
1896 if (readBuffer && drawBuffer)
1897 {
1898 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1899 dstX0, dstY0, dstX1, dstY1))
1900 {
1901 // only whole-buffer copies are permitted
1902 ERR(
1903 "Only whole-buffer depth and stencil blits are supported by this "
1904 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001906 return false;
1907 }
1908
1909 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1910 {
Jamie Madill437fa652016-05-03 15:13:24 -04001911 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001912 return false;
1913 }
1914 }
1915 }
1916 }
1917
1918 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1919 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001920}
Jamie Madillc29968b2016-01-20 11:17:23 -05001921
1922bool ValidateClear(ValidationContext *context, GLbitfield mask)
1923{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001924 auto fbo = context->getGLState().getDrawFramebuffer();
1925 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001928 return false;
1929 }
1930
1931 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1932 {
Jamie Madill437fa652016-05-03 15:13:24 -04001933 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001934 return false;
1935 }
1936
1937 return true;
1938}
1939
1940bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1941{
1942 if (!context->getExtensions().drawBuffers)
1943 {
Jamie Madill437fa652016-05-03 15:13:24 -04001944 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001945 return false;
1946 }
1947
1948 return ValidateDrawBuffersBase(context, n, bufs);
1949}
1950
Jamie Madill73a84962016-02-12 09:27:23 -05001951bool ValidateTexImage2D(Context *context,
1952 GLenum target,
1953 GLint level,
1954 GLint internalformat,
1955 GLsizei width,
1956 GLsizei height,
1957 GLint border,
1958 GLenum format,
1959 GLenum type,
1960 const GLvoid *pixels)
1961{
Martin Radev1be913c2016-07-11 17:59:16 +03001962 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001963 {
1964 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1965 0, 0, width, height, border, format, type, pixels);
1966 }
1967
Martin Radev1be913c2016-07-11 17:59:16 +03001968 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001969 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1970 0, 0, width, height, 1, border, format, type, pixels);
1971}
1972
1973bool ValidateTexSubImage2D(Context *context,
1974 GLenum target,
1975 GLint level,
1976 GLint xoffset,
1977 GLint yoffset,
1978 GLsizei width,
1979 GLsizei height,
1980 GLenum format,
1981 GLenum type,
1982 const GLvoid *pixels)
1983{
1984
Martin Radev1be913c2016-07-11 17:59:16 +03001985 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001986 {
1987 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1988 yoffset, width, height, 0, format, type, pixels);
1989 }
1990
Martin Radev1be913c2016-07-11 17:59:16 +03001991 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001992 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1993 yoffset, 0, width, height, 1, 0, format, type, pixels);
1994}
1995
1996bool ValidateCompressedTexImage2D(Context *context,
1997 GLenum target,
1998 GLint level,
1999 GLenum internalformat,
2000 GLsizei width,
2001 GLsizei height,
2002 GLint border,
2003 GLsizei imageSize,
2004 const GLvoid *data)
2005{
Martin Radev1be913c2016-07-11 17:59:16 +03002006 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002007 {
2008 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
2009 0, width, height, border, GL_NONE, GL_NONE, data))
2010 {
2011 return false;
2012 }
2013 }
2014 else
2015 {
Martin Radev1be913c2016-07-11 17:59:16 +03002016 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002017 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
2018 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
2019 data))
2020 {
2021 return false;
2022 }
2023 }
2024
2025 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002026 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002027 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002028 if (blockSizeOrErr.isError())
2029 {
2030 context->handleError(blockSizeOrErr.getError());
2031 return false;
2032 }
2033
2034 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002037 return false;
2038 }
2039
2040 return true;
2041}
2042
2043bool ValidateCompressedTexSubImage2D(Context *context,
2044 GLenum target,
2045 GLint level,
2046 GLint xoffset,
2047 GLint yoffset,
2048 GLsizei width,
2049 GLsizei height,
2050 GLenum format,
2051 GLsizei imageSize,
2052 const GLvoid *data)
2053{
Martin Radev1be913c2016-07-11 17:59:16 +03002054 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002055 {
2056 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2057 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2058 {
2059 return false;
2060 }
2061 }
2062 else
2063 {
Martin Radev1be913c2016-07-11 17:59:16 +03002064 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002065 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2066 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2067 data))
2068 {
2069 return false;
2070 }
2071 }
2072
2073 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002074 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002075 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002076 if (blockSizeOrErr.isError())
2077 {
2078 context->handleError(blockSizeOrErr.getError());
2079 return false;
2080 }
2081
2082 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002083 {
Jamie Madill437fa652016-05-03 15:13:24 -04002084 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002085 return false;
2086 }
2087
2088 return true;
2089}
2090
Olli Etuaho4f667482016-03-30 15:56:35 +03002091bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2092{
2093 if (!context->getExtensions().mapBuffer)
2094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002096 return false;
2097 }
2098
2099 return ValidateGetBufferPointervBase(context, target, pname, params);
2100}
2101
2102bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2103{
2104 if (!context->getExtensions().mapBuffer)
2105 {
Jamie Madill437fa652016-05-03 15:13:24 -04002106 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002107 return false;
2108 }
2109
2110 if (!ValidBufferTarget(context, target))
2111 {
Jamie Madill437fa652016-05-03 15:13:24 -04002112 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002113 return false;
2114 }
2115
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002116 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002117
2118 if (buffer == nullptr)
2119 {
Jamie Madill437fa652016-05-03 15:13:24 -04002120 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002121 return false;
2122 }
2123
2124 if (access != GL_WRITE_ONLY_OES)
2125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002127 return false;
2128 }
2129
2130 if (buffer->isMapped())
2131 {
Jamie Madill437fa652016-05-03 15:13:24 -04002132 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002133 return false;
2134 }
2135
2136 return true;
2137}
2138
2139bool ValidateUnmapBufferOES(Context *context, GLenum target)
2140{
2141 if (!context->getExtensions().mapBuffer)
2142 {
Jamie Madill437fa652016-05-03 15:13:24 -04002143 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002144 return false;
2145 }
2146
2147 return ValidateUnmapBufferBase(context, target);
2148}
2149
2150bool ValidateMapBufferRangeEXT(Context *context,
2151 GLenum target,
2152 GLintptr offset,
2153 GLsizeiptr length,
2154 GLbitfield access)
2155{
2156 if (!context->getExtensions().mapBufferRange)
2157 {
Jamie Madill437fa652016-05-03 15:13:24 -04002158 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002159 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2160 return false;
2161 }
2162
2163 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2164}
2165
2166bool ValidateFlushMappedBufferRangeEXT(Context *context,
2167 GLenum target,
2168 GLintptr offset,
2169 GLsizeiptr length)
2170{
2171 if (!context->getExtensions().mapBufferRange)
2172 {
Jamie Madill437fa652016-05-03 15:13:24 -04002173 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002174 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2175 return false;
2176 }
2177
2178 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2179}
2180
Ian Ewell54f87462016-03-10 13:47:21 -05002181bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2182{
2183 Texture *textureObject = context->getTexture(texture);
2184 if (textureObject && textureObject->getTarget() != target && texture != 0)
2185 {
Jamie Madill437fa652016-05-03 15:13:24 -04002186 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002187 return false;
2188 }
2189
2190 switch (target)
2191 {
2192 case GL_TEXTURE_2D:
2193 case GL_TEXTURE_CUBE_MAP:
2194 break;
2195
2196 case GL_TEXTURE_3D:
2197 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002198 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002201 return false;
2202 }
2203 break;
2204 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002205 if (!context->getExtensions().eglImageExternal &&
2206 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002207 {
Jamie Madill437fa652016-05-03 15:13:24 -04002208 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002209 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2210 return false;
2211 }
2212 break;
2213 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002214 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002215 return false;
2216 }
2217
2218 return true;
2219}
2220
Geoff Langd8605522016-04-13 10:19:12 -04002221bool ValidateBindUniformLocationCHROMIUM(Context *context,
2222 GLuint program,
2223 GLint location,
2224 const GLchar *name)
2225{
2226 if (!context->getExtensions().bindUniformLocation)
2227 {
Jamie Madill437fa652016-05-03 15:13:24 -04002228 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002229 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2230 return false;
2231 }
2232
2233 Program *programObject = GetValidProgram(context, program);
2234 if (!programObject)
2235 {
2236 return false;
2237 }
2238
2239 if (location < 0)
2240 {
Jamie Madill437fa652016-05-03 15:13:24 -04002241 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002242 return false;
2243 }
2244
2245 const Caps &caps = context->getCaps();
2246 if (static_cast<size_t>(location) >=
2247 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2248 {
Jamie Madill437fa652016-05-03 15:13:24 -04002249 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002250 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2251 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2252 return false;
2253 }
2254
2255 if (strncmp(name, "gl_", 3) == 0)
2256 {
Jamie Madill437fa652016-05-03 15:13:24 -04002257 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002258 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2259 return false;
2260 }
2261
2262 return true;
2263}
2264
Jamie Madille2e406c2016-06-02 13:04:10 -04002265bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002266{
2267 if (!context->getExtensions().framebufferMixedSamples)
2268 {
2269 context->handleError(
2270 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2271 return false;
2272 }
2273 switch (components)
2274 {
2275 case GL_RGB:
2276 case GL_RGBA:
2277 case GL_ALPHA:
2278 case GL_NONE:
2279 break;
2280 default:
2281 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002282 Error(GL_INVALID_ENUM,
2283 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002284 return false;
2285 }
2286
2287 return true;
2288}
2289
Sami Väisänene45e53b2016-05-25 10:36:04 +03002290// CHROMIUM_path_rendering
2291
2292bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2293{
2294 if (!context->getExtensions().pathRendering)
2295 {
2296 context->handleError(
2297 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2298 return false;
2299 }
2300 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2301 {
2302 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2303 return false;
2304 }
2305 if (matrix == nullptr)
2306 {
2307 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2308 return false;
2309 }
2310 return true;
2311}
2312
2313bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2314{
2315 if (!context->getExtensions().pathRendering)
2316 {
2317 context->handleError(
2318 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2319 return false;
2320 }
2321 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2322 {
2323 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2324 return false;
2325 }
2326 return true;
2327}
2328
2329bool ValidateGenPaths(Context *context, GLsizei range)
2330{
2331 if (!context->getExtensions().pathRendering)
2332 {
2333 context->handleError(
2334 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2335 return false;
2336 }
2337
2338 // range = 0 is undefined in NV_path_rendering.
2339 // we add stricter semantic check here and require a non zero positive range.
2340 if (range <= 0)
2341 {
2342 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2343 return false;
2344 }
2345
2346 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2347 {
2348 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2349 return false;
2350 }
2351
2352 return true;
2353}
2354
2355bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2356{
2357 if (!context->getExtensions().pathRendering)
2358 {
2359 context->handleError(
2360 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2361 return false;
2362 }
2363
2364 // range = 0 is undefined in NV_path_rendering.
2365 // we add stricter semantic check here and require a non zero positive range.
2366 if (range <= 0)
2367 {
2368 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2369 return false;
2370 }
2371
2372 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2373 checkedRange += range;
2374
2375 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2376 {
2377 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2378 return false;
2379 }
2380 return true;
2381}
2382
2383bool ValidatePathCommands(Context *context,
2384 GLuint path,
2385 GLsizei numCommands,
2386 const GLubyte *commands,
2387 GLsizei numCoords,
2388 GLenum coordType,
2389 const void *coords)
2390{
2391 if (!context->getExtensions().pathRendering)
2392 {
2393 context->handleError(
2394 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2395 return false;
2396 }
2397 if (!context->hasPath(path))
2398 {
2399 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2400 return false;
2401 }
2402
2403 if (numCommands < 0)
2404 {
2405 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2406 return false;
2407 }
2408 else if (numCommands > 0)
2409 {
2410 if (!commands)
2411 {
2412 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2413 return false;
2414 }
2415 }
2416
2417 if (numCoords < 0)
2418 {
2419 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2420 return false;
2421 }
2422 else if (numCoords > 0)
2423 {
2424 if (!coords)
2425 {
2426 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2427 return false;
2428 }
2429 }
2430
2431 std::uint32_t coordTypeSize = 0;
2432 switch (coordType)
2433 {
2434 case GL_BYTE:
2435 coordTypeSize = sizeof(GLbyte);
2436 break;
2437
2438 case GL_UNSIGNED_BYTE:
2439 coordTypeSize = sizeof(GLubyte);
2440 break;
2441
2442 case GL_SHORT:
2443 coordTypeSize = sizeof(GLshort);
2444 break;
2445
2446 case GL_UNSIGNED_SHORT:
2447 coordTypeSize = sizeof(GLushort);
2448 break;
2449
2450 case GL_FLOAT:
2451 coordTypeSize = sizeof(GLfloat);
2452 break;
2453
2454 default:
2455 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2456 return false;
2457 }
2458
2459 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2460 checkedSize += (coordTypeSize * numCoords);
2461 if (!checkedSize.IsValid())
2462 {
2463 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2464 return false;
2465 }
2466
2467 // early return skips command data validation when it doesn't exist.
2468 if (!commands)
2469 return true;
2470
2471 GLsizei expectedNumCoords = 0;
2472 for (GLsizei i = 0; i < numCommands; ++i)
2473 {
2474 switch (commands[i])
2475 {
2476 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2477 break;
2478 case GL_MOVE_TO_CHROMIUM:
2479 case GL_LINE_TO_CHROMIUM:
2480 expectedNumCoords += 2;
2481 break;
2482 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2483 expectedNumCoords += 4;
2484 break;
2485 case GL_CUBIC_CURVE_TO_CHROMIUM:
2486 expectedNumCoords += 6;
2487 break;
2488 case GL_CONIC_CURVE_TO_CHROMIUM:
2489 expectedNumCoords += 5;
2490 break;
2491 default:
2492 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2493 return false;
2494 }
2495 }
2496 if (expectedNumCoords != numCoords)
2497 {
2498 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2499 return false;
2500 }
2501
2502 return true;
2503}
2504
2505bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2506{
2507 if (!context->getExtensions().pathRendering)
2508 {
2509 context->handleError(
2510 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2511 return false;
2512 }
2513 if (!context->hasPath(path))
2514 {
2515 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2516 return false;
2517 }
2518
2519 switch (pname)
2520 {
2521 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2522 if (value < 0.0f)
2523 {
2524 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2525 return false;
2526 }
2527 break;
2528 case GL_PATH_END_CAPS_CHROMIUM:
2529 switch (static_cast<GLenum>(value))
2530 {
2531 case GL_FLAT_CHROMIUM:
2532 case GL_SQUARE_CHROMIUM:
2533 case GL_ROUND_CHROMIUM:
2534 break;
2535 default:
2536 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2537 return false;
2538 }
2539 break;
2540 case GL_PATH_JOIN_STYLE_CHROMIUM:
2541 switch (static_cast<GLenum>(value))
2542 {
2543 case GL_MITER_REVERT_CHROMIUM:
2544 case GL_BEVEL_CHROMIUM:
2545 case GL_ROUND_CHROMIUM:
2546 break;
2547 default:
2548 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2549 return false;
2550 }
2551 case GL_PATH_MITER_LIMIT_CHROMIUM:
2552 if (value < 0.0f)
2553 {
2554 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2555 return false;
2556 }
2557 break;
2558
2559 case GL_PATH_STROKE_BOUND_CHROMIUM:
2560 // no errors, only clamping.
2561 break;
2562
2563 default:
2564 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2565 return false;
2566 }
2567 return true;
2568}
2569
2570bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2571{
2572 if (!context->getExtensions().pathRendering)
2573 {
2574 context->handleError(
2575 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2576 return false;
2577 }
2578
2579 if (!context->hasPath(path))
2580 {
2581 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2582 return false;
2583 }
2584 if (!value)
2585 {
2586 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2587 return false;
2588 }
2589
2590 switch (pname)
2591 {
2592 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2593 case GL_PATH_END_CAPS_CHROMIUM:
2594 case GL_PATH_JOIN_STYLE_CHROMIUM:
2595 case GL_PATH_MITER_LIMIT_CHROMIUM:
2596 case GL_PATH_STROKE_BOUND_CHROMIUM:
2597 break;
2598
2599 default:
2600 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2601 return false;
2602 }
2603
2604 return true;
2605}
2606
2607bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2608{
2609 if (!context->getExtensions().pathRendering)
2610 {
2611 context->handleError(
2612 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2613 return false;
2614 }
2615
2616 switch (func)
2617 {
2618 case GL_NEVER:
2619 case GL_ALWAYS:
2620 case GL_LESS:
2621 case GL_LEQUAL:
2622 case GL_EQUAL:
2623 case GL_GEQUAL:
2624 case GL_GREATER:
2625 case GL_NOTEQUAL:
2626 break;
2627 default:
2628 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2629 return false;
2630 }
2631
2632 return true;
2633}
2634
2635// Note that the spec specifies that for the path drawing commands
2636// if the path object is not an existing path object the command
2637// does nothing and no error is generated.
2638// However if the path object exists but has not been specified any
2639// commands then an error is generated.
2640
2641bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2642{
2643 if (!context->getExtensions().pathRendering)
2644 {
2645 context->handleError(
2646 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2647 return false;
2648 }
2649 if (context->hasPath(path) && !context->hasPathData(path))
2650 {
2651 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2652 return false;
2653 }
2654
2655 switch (fillMode)
2656 {
2657 case GL_COUNT_UP_CHROMIUM:
2658 case GL_COUNT_DOWN_CHROMIUM:
2659 break;
2660 default:
2661 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2662 return false;
2663 }
2664
2665 if (!isPow2(mask + 1))
2666 {
2667 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2668 return false;
2669 }
2670
2671 return true;
2672}
2673
2674bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2675{
2676 if (!context->getExtensions().pathRendering)
2677 {
2678 context->handleError(
2679 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2680 return false;
2681 }
2682 if (context->hasPath(path) && !context->hasPathData(path))
2683 {
2684 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2685 return false;
2686 }
2687
2688 return true;
2689}
2690
2691bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2692{
2693 if (!context->getExtensions().pathRendering)
2694 {
2695 context->handleError(
2696 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2697 return false;
2698 }
2699 if (context->hasPath(path) && !context->hasPathData(path))
2700 {
2701 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2702 return false;
2703 }
2704
2705 switch (coverMode)
2706 {
2707 case GL_CONVEX_HULL_CHROMIUM:
2708 case GL_BOUNDING_BOX_CHROMIUM:
2709 break;
2710 default:
2711 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2712 return false;
2713 }
2714 return true;
2715}
2716
2717bool ValidateStencilThenCoverFillPath(Context *context,
2718 GLuint path,
2719 GLenum fillMode,
2720 GLuint mask,
2721 GLenum coverMode)
2722{
2723 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2724 ValidateCoverPath(context, path, coverMode);
2725}
2726
2727bool ValidateStencilThenCoverStrokePath(Context *context,
2728 GLuint path,
2729 GLint reference,
2730 GLuint mask,
2731 GLenum coverMode)
2732{
2733 return ValidateStencilStrokePath(context, path, reference, mask) &&
2734 ValidateCoverPath(context, path, coverMode);
2735}
2736
2737bool ValidateIsPath(Context *context)
2738{
2739 if (!context->getExtensions().pathRendering)
2740 {
2741 context->handleError(
2742 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2743 return false;
2744 }
2745 return true;
2746}
2747
Sami Väisänend59ca052016-06-21 16:10:00 +03002748bool ValidateCoverFillPathInstanced(Context *context,
2749 GLsizei numPaths,
2750 GLenum pathNameType,
2751 const void *paths,
2752 GLuint pathBase,
2753 GLenum coverMode,
2754 GLenum transformType,
2755 const GLfloat *transformValues)
2756{
2757 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2758 transformType, transformValues))
2759 return false;
2760
2761 switch (coverMode)
2762 {
2763 case GL_CONVEX_HULL_CHROMIUM:
2764 case GL_BOUNDING_BOX_CHROMIUM:
2765 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2766 break;
2767 default:
2768 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2769 return false;
2770 }
2771
2772 return true;
2773}
2774
2775bool ValidateCoverStrokePathInstanced(Context *context,
2776 GLsizei numPaths,
2777 GLenum pathNameType,
2778 const void *paths,
2779 GLuint pathBase,
2780 GLenum coverMode,
2781 GLenum transformType,
2782 const GLfloat *transformValues)
2783{
2784 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2785 transformType, transformValues))
2786 return false;
2787
2788 switch (coverMode)
2789 {
2790 case GL_CONVEX_HULL_CHROMIUM:
2791 case GL_BOUNDING_BOX_CHROMIUM:
2792 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2793 break;
2794 default:
2795 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2796 return false;
2797 }
2798
2799 return true;
2800}
2801
2802bool ValidateStencilFillPathInstanced(Context *context,
2803 GLsizei numPaths,
2804 GLenum pathNameType,
2805 const void *paths,
2806 GLuint pathBase,
2807 GLenum fillMode,
2808 GLuint mask,
2809 GLenum transformType,
2810 const GLfloat *transformValues)
2811{
2812
2813 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2814 transformType, transformValues))
2815 return false;
2816
2817 switch (fillMode)
2818 {
2819 case GL_COUNT_UP_CHROMIUM:
2820 case GL_COUNT_DOWN_CHROMIUM:
2821 break;
2822 default:
2823 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2824 return false;
2825 }
2826 if (!isPow2(mask + 1))
2827 {
2828 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2829 return false;
2830 }
2831 return true;
2832}
2833
2834bool ValidateStencilStrokePathInstanced(Context *context,
2835 GLsizei numPaths,
2836 GLenum pathNameType,
2837 const void *paths,
2838 GLuint pathBase,
2839 GLint reference,
2840 GLuint mask,
2841 GLenum transformType,
2842 const GLfloat *transformValues)
2843{
2844 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2845 transformType, transformValues))
2846 return false;
2847
2848 // no more validation here.
2849
2850 return true;
2851}
2852
2853bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2854 GLsizei numPaths,
2855 GLenum pathNameType,
2856 const void *paths,
2857 GLuint pathBase,
2858 GLenum fillMode,
2859 GLuint mask,
2860 GLenum coverMode,
2861 GLenum transformType,
2862 const GLfloat *transformValues)
2863{
2864 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2865 transformType, transformValues))
2866 return false;
2867
2868 switch (coverMode)
2869 {
2870 case GL_CONVEX_HULL_CHROMIUM:
2871 case GL_BOUNDING_BOX_CHROMIUM:
2872 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2873 break;
2874 default:
2875 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2876 return false;
2877 }
2878
2879 switch (fillMode)
2880 {
2881 case GL_COUNT_UP_CHROMIUM:
2882 case GL_COUNT_DOWN_CHROMIUM:
2883 break;
2884 default:
2885 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2886 return false;
2887 }
2888 if (!isPow2(mask + 1))
2889 {
2890 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2891 return false;
2892 }
2893
2894 return true;
2895}
2896
2897bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2898 GLsizei numPaths,
2899 GLenum pathNameType,
2900 const void *paths,
2901 GLuint pathBase,
2902 GLint reference,
2903 GLuint mask,
2904 GLenum coverMode,
2905 GLenum transformType,
2906 const GLfloat *transformValues)
2907{
2908 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2909 transformType, transformValues))
2910 return false;
2911
2912 switch (coverMode)
2913 {
2914 case GL_CONVEX_HULL_CHROMIUM:
2915 case GL_BOUNDING_BOX_CHROMIUM:
2916 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2917 break;
2918 default:
2919 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2920 return false;
2921 }
2922
2923 return true;
2924}
2925
Sami Väisänen46eaa942016-06-29 10:26:37 +03002926bool ValidateBindFragmentInputLocation(Context *context,
2927 GLuint program,
2928 GLint location,
2929 const GLchar *name)
2930{
2931 if (!context->getExtensions().pathRendering)
2932 {
2933 context->handleError(
2934 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2935 return false;
2936 }
2937
2938 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2939 if (location >= MaxLocation)
2940 {
2941 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2942 return false;
2943 }
2944
2945 const auto *programObject = context->getProgram(program);
2946 if (!programObject)
2947 {
2948 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2949 return false;
2950 }
2951
2952 if (!name)
2953 {
2954 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2955 return false;
2956 }
2957
2958 if (angle::BeginsWith(name, "gl_"))
2959 {
2960 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2961 return false;
2962 }
2963
2964 return true;
2965}
2966
2967bool ValidateProgramPathFragmentInputGen(Context *context,
2968 GLuint program,
2969 GLint location,
2970 GLenum genMode,
2971 GLint components,
2972 const GLfloat *coeffs)
2973{
2974 if (!context->getExtensions().pathRendering)
2975 {
2976 context->handleError(
2977 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2978 return false;
2979 }
2980
2981 const auto *programObject = context->getProgram(program);
2982 if (!programObject || programObject->isFlaggedForDeletion())
2983 {
2984 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2985 return false;
2986 }
2987
2988 if (!programObject->isLinked())
2989 {
2990 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2991 return false;
2992 }
2993
2994 switch (genMode)
2995 {
2996 case GL_NONE:
2997 if (components != 0)
2998 {
2999 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3000 return false;
3001 }
3002 break;
3003
3004 case GL_OBJECT_LINEAR_CHROMIUM:
3005 case GL_EYE_LINEAR_CHROMIUM:
3006 case GL_CONSTANT_CHROMIUM:
3007 if (components < 1 || components > 4)
3008 {
3009 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3010 return false;
3011 }
3012 if (!coeffs)
3013 {
3014 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3015 return false;
3016 }
3017 break;
3018
3019 default:
3020 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3021 return false;
3022 }
3023
3024 // If the location is -1 then the command is silently ignored
3025 // and no further validation is needed.
3026 if (location == -1)
3027 return true;
3028
3029 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3030
3031 if (!binding.valid)
3032 {
3033 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3034 return false;
3035 }
3036
3037 if (binding.type != GL_NONE)
3038 {
3039 GLint expectedComponents = 0;
3040 switch (binding.type)
3041 {
3042 case GL_FLOAT:
3043 expectedComponents = 1;
3044 break;
3045 case GL_FLOAT_VEC2:
3046 expectedComponents = 2;
3047 break;
3048 case GL_FLOAT_VEC3:
3049 expectedComponents = 3;
3050 break;
3051 case GL_FLOAT_VEC4:
3052 expectedComponents = 4;
3053 break;
3054 default:
3055 context->handleError(Error(GL_INVALID_OPERATION,
3056 "Fragment input type is not a floating point scalar or vector."));
3057 return false;
3058 }
3059 if (expectedComponents != components && genMode != GL_NONE)
3060 {
3061 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3062 return false;
3063 }
3064 }
3065 return true;
3066}
3067
Geoff Lang97073d12016-04-20 10:42:34 -07003068bool ValidateCopyTextureCHROMIUM(Context *context,
3069 GLuint sourceId,
3070 GLuint destId,
3071 GLint internalFormat,
3072 GLenum destType,
3073 GLboolean unpackFlipY,
3074 GLboolean unpackPremultiplyAlpha,
3075 GLboolean unpackUnmultiplyAlpha)
3076{
3077 if (!context->getExtensions().copyTexture)
3078 {
3079 context->handleError(
3080 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3081 return false;
3082 }
3083
3084 const gl::Texture *source = context->getTexture(sourceId);
3085 if (source == nullptr)
3086 {
3087 context->handleError(
3088 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3089 return false;
3090 }
3091
3092 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3093 {
3094 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3095 return false;
3096 }
3097
3098 GLenum sourceTarget = source->getTarget();
3099 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3100 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3101 {
3102 context->handleError(
3103 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3104 return false;
3105 }
3106
3107 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3108 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3109 {
3110 context->handleError(
3111 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3112 return false;
3113 }
3114
3115 const gl::Texture *dest = context->getTexture(destId);
3116 if (dest == nullptr)
3117 {
3118 context->handleError(
3119 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3120 return false;
3121 }
3122
3123 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3124 {
3125 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3126 return false;
3127 }
3128
3129 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3130 {
3131 context->handleError(
3132 Error(GL_INVALID_OPERATION,
3133 "Destination internal format and type combination is not valid."));
3134 return false;
3135 }
3136
3137 if (dest->getImmutableFormat())
3138 {
3139 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3140 return false;
3141 }
3142
3143 return true;
3144}
3145
3146bool ValidateCopySubTextureCHROMIUM(Context *context,
3147 GLuint sourceId,
3148 GLuint destId,
3149 GLint xoffset,
3150 GLint yoffset,
3151 GLint x,
3152 GLint y,
3153 GLsizei width,
3154 GLsizei height,
3155 GLboolean unpackFlipY,
3156 GLboolean unpackPremultiplyAlpha,
3157 GLboolean unpackUnmultiplyAlpha)
3158{
3159 if (!context->getExtensions().copyTexture)
3160 {
3161 context->handleError(
3162 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3163 return false;
3164 }
3165
3166 const gl::Texture *source = context->getTexture(sourceId);
3167 if (source == nullptr)
3168 {
3169 context->handleError(
3170 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3171 return false;
3172 }
3173
3174 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3175 {
3176 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3177 return false;
3178 }
3179
3180 GLenum sourceTarget = source->getTarget();
3181 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3182 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3183 {
3184 context->handleError(
3185 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3186 return false;
3187 }
3188
3189 if (x < 0 || y < 0)
3190 {
3191 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3192 return false;
3193 }
3194
3195 if (width < 0 || height < 0)
3196 {
3197 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3198 return false;
3199 }
3200
3201 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3202 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3203 {
3204 context->handleError(
3205 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3206 return false;
3207 }
3208
3209 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3210 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3211 {
3212 context->handleError(
3213 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3214 return false;
3215 }
3216
3217 const gl::Texture *dest = context->getTexture(destId);
3218 if (dest == nullptr)
3219 {
3220 context->handleError(
3221 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3222 return false;
3223 }
3224
3225 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3226 {
3227 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3228 return false;
3229 }
3230
3231 GLenum destTarget = dest->getTarget();
3232 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3233 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3234 {
3235 context->handleError(
3236 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3237 return false;
3238 }
3239
3240 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3241 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3242 {
3243 context->handleError(
3244 Error(GL_INVALID_OPERATION,
3245 "Destination internal format and type combination is not valid."));
3246 return false;
3247 }
3248
3249 if (xoffset < 0 || yoffset < 0)
3250 {
3251 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3252 return false;
3253 }
3254
3255 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3256 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3257 {
3258 context->handleError(
3259 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3260 return false;
3261 }
3262
3263 return true;
3264}
3265
Martin Radev4c4c8e72016-08-04 12:25:34 +03003266bool ValidateCreateShader(Context *context, GLenum type)
3267{
3268 switch (type)
3269 {
3270 case GL_VERTEX_SHADER:
3271 case GL_FRAGMENT_SHADER:
3272 break;
3273 case GL_COMPUTE_SHADER:
3274 if (context->getGLVersion().isES31())
3275 {
3276 break;
3277 }
3278 default:
3279 context->handleError(Error(GL_INVALID_ENUM));
3280 return false;
3281 }
Jamie Madill29639852016-09-02 15:00:09 -04003282
3283 return true;
3284}
3285
3286bool ValidateBufferData(ValidationContext *context,
3287 GLenum target,
3288 GLsizeiptr size,
3289 const GLvoid *data,
3290 GLenum usage)
3291{
3292 if (size < 0)
3293 {
3294 context->handleError(Error(GL_INVALID_VALUE));
3295 return false;
3296 }
3297
3298 switch (usage)
3299 {
3300 case GL_STREAM_DRAW:
3301 case GL_STATIC_DRAW:
3302 case GL_DYNAMIC_DRAW:
3303 break;
3304
3305 case GL_STREAM_READ:
3306 case GL_STREAM_COPY:
3307 case GL_STATIC_READ:
3308 case GL_STATIC_COPY:
3309 case GL_DYNAMIC_READ:
3310 case GL_DYNAMIC_COPY:
3311 if (context->getClientMajorVersion() < 3)
3312 {
3313 context->handleError(Error(GL_INVALID_ENUM));
3314 return false;
3315 }
3316 break;
3317
3318 default:
3319 context->handleError(Error(GL_INVALID_ENUM));
3320 return false;
3321 }
3322
3323 if (!ValidBufferTarget(context, target))
3324 {
3325 context->handleError(Error(GL_INVALID_ENUM));
3326 return false;
3327 }
3328
3329 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3330
3331 if (!buffer)
3332 {
3333 context->handleError(Error(GL_INVALID_OPERATION));
3334 return false;
3335 }
3336
3337 return true;
3338}
3339
3340bool ValidateBufferSubData(ValidationContext *context,
3341 GLenum target,
3342 GLintptr offset,
3343 GLsizeiptr size,
3344 const GLvoid *data)
3345{
3346 if (size < 0 || offset < 0)
3347 {
3348 context->handleError(Error(GL_INVALID_VALUE));
3349 return false;
3350 }
3351
3352 if (!ValidBufferTarget(context, target))
3353 {
3354 context->handleError(Error(GL_INVALID_ENUM));
3355 return false;
3356 }
3357
3358 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3359
3360 if (!buffer)
3361 {
3362 context->handleError(Error(GL_INVALID_OPERATION));
3363 return false;
3364 }
3365
3366 if (buffer->isMapped())
3367 {
3368 context->handleError(Error(GL_INVALID_OPERATION));
3369 return false;
3370 }
3371
3372 // Check for possible overflow of size + offset
3373 angle::CheckedNumeric<size_t> checkedSize(size);
3374 checkedSize += offset;
3375 if (!checkedSize.IsValid())
3376 {
3377 context->handleError(Error(GL_OUT_OF_MEMORY));
3378 return false;
3379 }
3380
3381 if (size + offset > buffer->getSize())
3382 {
3383 context->handleError(Error(GL_INVALID_VALUE));
3384 return false;
3385 }
3386
Martin Radev4c4c8e72016-08-04 12:25:34 +03003387 return true;
3388}
3389
Geoff Langc287ea62016-09-16 14:46:51 -04003390bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3391{
3392 if (!context->getExtensions().webglCompatibility)
3393 {
3394 context->handleError(
3395 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3396 return false;
3397 }
3398
3399 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3400 auto extension = extensionInfos.find(name);
3401 if (extension == extensionInfos.end() || !extension->second.Enableable)
3402 {
3403 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3404 return false;
3405 }
3406
3407 return true;
3408}
3409
Jamie Madillc29968b2016-01-20 11:17:23 -05003410} // namespace gl