blob: d28874885bb99ed2559a5faa9bb79e2881ea730c [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
Geoff Langf41a7152016-09-19 15:11:17 -04002190 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2191 !context->isTextureGenerated(texture))
2192 {
2193 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2194 return false;
2195 }
2196
Ian Ewell54f87462016-03-10 13:47:21 -05002197 switch (target)
2198 {
2199 case GL_TEXTURE_2D:
2200 case GL_TEXTURE_CUBE_MAP:
2201 break;
2202
2203 case GL_TEXTURE_3D:
2204 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002205 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002206 {
Jamie Madill437fa652016-05-03 15:13:24 -04002207 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002208 return false;
2209 }
2210 break;
2211 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002212 if (!context->getExtensions().eglImageExternal &&
2213 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002214 {
Jamie Madill437fa652016-05-03 15:13:24 -04002215 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002216 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2217 return false;
2218 }
2219 break;
2220 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002221 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002222 return false;
2223 }
2224
2225 return true;
2226}
2227
Geoff Langd8605522016-04-13 10:19:12 -04002228bool ValidateBindUniformLocationCHROMIUM(Context *context,
2229 GLuint program,
2230 GLint location,
2231 const GLchar *name)
2232{
2233 if (!context->getExtensions().bindUniformLocation)
2234 {
Jamie Madill437fa652016-05-03 15:13:24 -04002235 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002236 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2237 return false;
2238 }
2239
2240 Program *programObject = GetValidProgram(context, program);
2241 if (!programObject)
2242 {
2243 return false;
2244 }
2245
2246 if (location < 0)
2247 {
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002249 return false;
2250 }
2251
2252 const Caps &caps = context->getCaps();
2253 if (static_cast<size_t>(location) >=
2254 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2255 {
Jamie Madill437fa652016-05-03 15:13:24 -04002256 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002257 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2258 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2259 return false;
2260 }
2261
2262 if (strncmp(name, "gl_", 3) == 0)
2263 {
Jamie Madill437fa652016-05-03 15:13:24 -04002264 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002265 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2266 return false;
2267 }
2268
2269 return true;
2270}
2271
Jamie Madille2e406c2016-06-02 13:04:10 -04002272bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002273{
2274 if (!context->getExtensions().framebufferMixedSamples)
2275 {
2276 context->handleError(
2277 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2278 return false;
2279 }
2280 switch (components)
2281 {
2282 case GL_RGB:
2283 case GL_RGBA:
2284 case GL_ALPHA:
2285 case GL_NONE:
2286 break;
2287 default:
2288 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002289 Error(GL_INVALID_ENUM,
2290 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002291 return false;
2292 }
2293
2294 return true;
2295}
2296
Sami Väisänene45e53b2016-05-25 10:36:04 +03002297// CHROMIUM_path_rendering
2298
2299bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2300{
2301 if (!context->getExtensions().pathRendering)
2302 {
2303 context->handleError(
2304 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2305 return false;
2306 }
2307 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2308 {
2309 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2310 return false;
2311 }
2312 if (matrix == nullptr)
2313 {
2314 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2315 return false;
2316 }
2317 return true;
2318}
2319
2320bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2321{
2322 if (!context->getExtensions().pathRendering)
2323 {
2324 context->handleError(
2325 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2326 return false;
2327 }
2328 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2329 {
2330 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2331 return false;
2332 }
2333 return true;
2334}
2335
2336bool ValidateGenPaths(Context *context, GLsizei range)
2337{
2338 if (!context->getExtensions().pathRendering)
2339 {
2340 context->handleError(
2341 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2342 return false;
2343 }
2344
2345 // range = 0 is undefined in NV_path_rendering.
2346 // we add stricter semantic check here and require a non zero positive range.
2347 if (range <= 0)
2348 {
2349 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2350 return false;
2351 }
2352
2353 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2354 {
2355 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2356 return false;
2357 }
2358
2359 return true;
2360}
2361
2362bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2363{
2364 if (!context->getExtensions().pathRendering)
2365 {
2366 context->handleError(
2367 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2368 return false;
2369 }
2370
2371 // range = 0 is undefined in NV_path_rendering.
2372 // we add stricter semantic check here and require a non zero positive range.
2373 if (range <= 0)
2374 {
2375 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2376 return false;
2377 }
2378
2379 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2380 checkedRange += range;
2381
2382 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2383 {
2384 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2385 return false;
2386 }
2387 return true;
2388}
2389
2390bool ValidatePathCommands(Context *context,
2391 GLuint path,
2392 GLsizei numCommands,
2393 const GLubyte *commands,
2394 GLsizei numCoords,
2395 GLenum coordType,
2396 const void *coords)
2397{
2398 if (!context->getExtensions().pathRendering)
2399 {
2400 context->handleError(
2401 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2402 return false;
2403 }
2404 if (!context->hasPath(path))
2405 {
2406 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2407 return false;
2408 }
2409
2410 if (numCommands < 0)
2411 {
2412 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2413 return false;
2414 }
2415 else if (numCommands > 0)
2416 {
2417 if (!commands)
2418 {
2419 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2420 return false;
2421 }
2422 }
2423
2424 if (numCoords < 0)
2425 {
2426 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2427 return false;
2428 }
2429 else if (numCoords > 0)
2430 {
2431 if (!coords)
2432 {
2433 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2434 return false;
2435 }
2436 }
2437
2438 std::uint32_t coordTypeSize = 0;
2439 switch (coordType)
2440 {
2441 case GL_BYTE:
2442 coordTypeSize = sizeof(GLbyte);
2443 break;
2444
2445 case GL_UNSIGNED_BYTE:
2446 coordTypeSize = sizeof(GLubyte);
2447 break;
2448
2449 case GL_SHORT:
2450 coordTypeSize = sizeof(GLshort);
2451 break;
2452
2453 case GL_UNSIGNED_SHORT:
2454 coordTypeSize = sizeof(GLushort);
2455 break;
2456
2457 case GL_FLOAT:
2458 coordTypeSize = sizeof(GLfloat);
2459 break;
2460
2461 default:
2462 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2463 return false;
2464 }
2465
2466 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2467 checkedSize += (coordTypeSize * numCoords);
2468 if (!checkedSize.IsValid())
2469 {
2470 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2471 return false;
2472 }
2473
2474 // early return skips command data validation when it doesn't exist.
2475 if (!commands)
2476 return true;
2477
2478 GLsizei expectedNumCoords = 0;
2479 for (GLsizei i = 0; i < numCommands; ++i)
2480 {
2481 switch (commands[i])
2482 {
2483 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2484 break;
2485 case GL_MOVE_TO_CHROMIUM:
2486 case GL_LINE_TO_CHROMIUM:
2487 expectedNumCoords += 2;
2488 break;
2489 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2490 expectedNumCoords += 4;
2491 break;
2492 case GL_CUBIC_CURVE_TO_CHROMIUM:
2493 expectedNumCoords += 6;
2494 break;
2495 case GL_CONIC_CURVE_TO_CHROMIUM:
2496 expectedNumCoords += 5;
2497 break;
2498 default:
2499 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2500 return false;
2501 }
2502 }
2503 if (expectedNumCoords != numCoords)
2504 {
2505 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2506 return false;
2507 }
2508
2509 return true;
2510}
2511
2512bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2513{
2514 if (!context->getExtensions().pathRendering)
2515 {
2516 context->handleError(
2517 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2518 return false;
2519 }
2520 if (!context->hasPath(path))
2521 {
2522 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2523 return false;
2524 }
2525
2526 switch (pname)
2527 {
2528 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2529 if (value < 0.0f)
2530 {
2531 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2532 return false;
2533 }
2534 break;
2535 case GL_PATH_END_CAPS_CHROMIUM:
2536 switch (static_cast<GLenum>(value))
2537 {
2538 case GL_FLAT_CHROMIUM:
2539 case GL_SQUARE_CHROMIUM:
2540 case GL_ROUND_CHROMIUM:
2541 break;
2542 default:
2543 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2544 return false;
2545 }
2546 break;
2547 case GL_PATH_JOIN_STYLE_CHROMIUM:
2548 switch (static_cast<GLenum>(value))
2549 {
2550 case GL_MITER_REVERT_CHROMIUM:
2551 case GL_BEVEL_CHROMIUM:
2552 case GL_ROUND_CHROMIUM:
2553 break;
2554 default:
2555 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2556 return false;
2557 }
2558 case GL_PATH_MITER_LIMIT_CHROMIUM:
2559 if (value < 0.0f)
2560 {
2561 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2562 return false;
2563 }
2564 break;
2565
2566 case GL_PATH_STROKE_BOUND_CHROMIUM:
2567 // no errors, only clamping.
2568 break;
2569
2570 default:
2571 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2572 return false;
2573 }
2574 return true;
2575}
2576
2577bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2578{
2579 if (!context->getExtensions().pathRendering)
2580 {
2581 context->handleError(
2582 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2583 return false;
2584 }
2585
2586 if (!context->hasPath(path))
2587 {
2588 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2589 return false;
2590 }
2591 if (!value)
2592 {
2593 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2594 return false;
2595 }
2596
2597 switch (pname)
2598 {
2599 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2600 case GL_PATH_END_CAPS_CHROMIUM:
2601 case GL_PATH_JOIN_STYLE_CHROMIUM:
2602 case GL_PATH_MITER_LIMIT_CHROMIUM:
2603 case GL_PATH_STROKE_BOUND_CHROMIUM:
2604 break;
2605
2606 default:
2607 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2608 return false;
2609 }
2610
2611 return true;
2612}
2613
2614bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2615{
2616 if (!context->getExtensions().pathRendering)
2617 {
2618 context->handleError(
2619 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2620 return false;
2621 }
2622
2623 switch (func)
2624 {
2625 case GL_NEVER:
2626 case GL_ALWAYS:
2627 case GL_LESS:
2628 case GL_LEQUAL:
2629 case GL_EQUAL:
2630 case GL_GEQUAL:
2631 case GL_GREATER:
2632 case GL_NOTEQUAL:
2633 break;
2634 default:
2635 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2636 return false;
2637 }
2638
2639 return true;
2640}
2641
2642// Note that the spec specifies that for the path drawing commands
2643// if the path object is not an existing path object the command
2644// does nothing and no error is generated.
2645// However if the path object exists but has not been specified any
2646// commands then an error is generated.
2647
2648bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2649{
2650 if (!context->getExtensions().pathRendering)
2651 {
2652 context->handleError(
2653 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2654 return false;
2655 }
2656 if (context->hasPath(path) && !context->hasPathData(path))
2657 {
2658 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2659 return false;
2660 }
2661
2662 switch (fillMode)
2663 {
2664 case GL_COUNT_UP_CHROMIUM:
2665 case GL_COUNT_DOWN_CHROMIUM:
2666 break;
2667 default:
2668 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2669 return false;
2670 }
2671
2672 if (!isPow2(mask + 1))
2673 {
2674 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2675 return false;
2676 }
2677
2678 return true;
2679}
2680
2681bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2682{
2683 if (!context->getExtensions().pathRendering)
2684 {
2685 context->handleError(
2686 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2687 return false;
2688 }
2689 if (context->hasPath(path) && !context->hasPathData(path))
2690 {
2691 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2692 return false;
2693 }
2694
2695 return true;
2696}
2697
2698bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2699{
2700 if (!context->getExtensions().pathRendering)
2701 {
2702 context->handleError(
2703 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2704 return false;
2705 }
2706 if (context->hasPath(path) && !context->hasPathData(path))
2707 {
2708 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2709 return false;
2710 }
2711
2712 switch (coverMode)
2713 {
2714 case GL_CONVEX_HULL_CHROMIUM:
2715 case GL_BOUNDING_BOX_CHROMIUM:
2716 break;
2717 default:
2718 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2719 return false;
2720 }
2721 return true;
2722}
2723
2724bool ValidateStencilThenCoverFillPath(Context *context,
2725 GLuint path,
2726 GLenum fillMode,
2727 GLuint mask,
2728 GLenum coverMode)
2729{
2730 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2731 ValidateCoverPath(context, path, coverMode);
2732}
2733
2734bool ValidateStencilThenCoverStrokePath(Context *context,
2735 GLuint path,
2736 GLint reference,
2737 GLuint mask,
2738 GLenum coverMode)
2739{
2740 return ValidateStencilStrokePath(context, path, reference, mask) &&
2741 ValidateCoverPath(context, path, coverMode);
2742}
2743
2744bool ValidateIsPath(Context *context)
2745{
2746 if (!context->getExtensions().pathRendering)
2747 {
2748 context->handleError(
2749 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2750 return false;
2751 }
2752 return true;
2753}
2754
Sami Väisänend59ca052016-06-21 16:10:00 +03002755bool ValidateCoverFillPathInstanced(Context *context,
2756 GLsizei numPaths,
2757 GLenum pathNameType,
2758 const void *paths,
2759 GLuint pathBase,
2760 GLenum coverMode,
2761 GLenum transformType,
2762 const GLfloat *transformValues)
2763{
2764 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2765 transformType, transformValues))
2766 return false;
2767
2768 switch (coverMode)
2769 {
2770 case GL_CONVEX_HULL_CHROMIUM:
2771 case GL_BOUNDING_BOX_CHROMIUM:
2772 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2773 break;
2774 default:
2775 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2776 return false;
2777 }
2778
2779 return true;
2780}
2781
2782bool ValidateCoverStrokePathInstanced(Context *context,
2783 GLsizei numPaths,
2784 GLenum pathNameType,
2785 const void *paths,
2786 GLuint pathBase,
2787 GLenum coverMode,
2788 GLenum transformType,
2789 const GLfloat *transformValues)
2790{
2791 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2792 transformType, transformValues))
2793 return false;
2794
2795 switch (coverMode)
2796 {
2797 case GL_CONVEX_HULL_CHROMIUM:
2798 case GL_BOUNDING_BOX_CHROMIUM:
2799 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2800 break;
2801 default:
2802 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2803 return false;
2804 }
2805
2806 return true;
2807}
2808
2809bool ValidateStencilFillPathInstanced(Context *context,
2810 GLsizei numPaths,
2811 GLenum pathNameType,
2812 const void *paths,
2813 GLuint pathBase,
2814 GLenum fillMode,
2815 GLuint mask,
2816 GLenum transformType,
2817 const GLfloat *transformValues)
2818{
2819
2820 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2821 transformType, transformValues))
2822 return false;
2823
2824 switch (fillMode)
2825 {
2826 case GL_COUNT_UP_CHROMIUM:
2827 case GL_COUNT_DOWN_CHROMIUM:
2828 break;
2829 default:
2830 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2831 return false;
2832 }
2833 if (!isPow2(mask + 1))
2834 {
2835 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2836 return false;
2837 }
2838 return true;
2839}
2840
2841bool ValidateStencilStrokePathInstanced(Context *context,
2842 GLsizei numPaths,
2843 GLenum pathNameType,
2844 const void *paths,
2845 GLuint pathBase,
2846 GLint reference,
2847 GLuint mask,
2848 GLenum transformType,
2849 const GLfloat *transformValues)
2850{
2851 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2852 transformType, transformValues))
2853 return false;
2854
2855 // no more validation here.
2856
2857 return true;
2858}
2859
2860bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2861 GLsizei numPaths,
2862 GLenum pathNameType,
2863 const void *paths,
2864 GLuint pathBase,
2865 GLenum fillMode,
2866 GLuint mask,
2867 GLenum coverMode,
2868 GLenum transformType,
2869 const GLfloat *transformValues)
2870{
2871 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2872 transformType, transformValues))
2873 return false;
2874
2875 switch (coverMode)
2876 {
2877 case GL_CONVEX_HULL_CHROMIUM:
2878 case GL_BOUNDING_BOX_CHROMIUM:
2879 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2880 break;
2881 default:
2882 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2883 return false;
2884 }
2885
2886 switch (fillMode)
2887 {
2888 case GL_COUNT_UP_CHROMIUM:
2889 case GL_COUNT_DOWN_CHROMIUM:
2890 break;
2891 default:
2892 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2893 return false;
2894 }
2895 if (!isPow2(mask + 1))
2896 {
2897 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2898 return false;
2899 }
2900
2901 return true;
2902}
2903
2904bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2905 GLsizei numPaths,
2906 GLenum pathNameType,
2907 const void *paths,
2908 GLuint pathBase,
2909 GLint reference,
2910 GLuint mask,
2911 GLenum coverMode,
2912 GLenum transformType,
2913 const GLfloat *transformValues)
2914{
2915 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2916 transformType, transformValues))
2917 return false;
2918
2919 switch (coverMode)
2920 {
2921 case GL_CONVEX_HULL_CHROMIUM:
2922 case GL_BOUNDING_BOX_CHROMIUM:
2923 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2924 break;
2925 default:
2926 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2927 return false;
2928 }
2929
2930 return true;
2931}
2932
Sami Väisänen46eaa942016-06-29 10:26:37 +03002933bool ValidateBindFragmentInputLocation(Context *context,
2934 GLuint program,
2935 GLint location,
2936 const GLchar *name)
2937{
2938 if (!context->getExtensions().pathRendering)
2939 {
2940 context->handleError(
2941 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2942 return false;
2943 }
2944
2945 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2946 if (location >= MaxLocation)
2947 {
2948 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2949 return false;
2950 }
2951
2952 const auto *programObject = context->getProgram(program);
2953 if (!programObject)
2954 {
2955 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2956 return false;
2957 }
2958
2959 if (!name)
2960 {
2961 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2962 return false;
2963 }
2964
2965 if (angle::BeginsWith(name, "gl_"))
2966 {
2967 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2968 return false;
2969 }
2970
2971 return true;
2972}
2973
2974bool ValidateProgramPathFragmentInputGen(Context *context,
2975 GLuint program,
2976 GLint location,
2977 GLenum genMode,
2978 GLint components,
2979 const GLfloat *coeffs)
2980{
2981 if (!context->getExtensions().pathRendering)
2982 {
2983 context->handleError(
2984 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2985 return false;
2986 }
2987
2988 const auto *programObject = context->getProgram(program);
2989 if (!programObject || programObject->isFlaggedForDeletion())
2990 {
2991 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2992 return false;
2993 }
2994
2995 if (!programObject->isLinked())
2996 {
2997 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2998 return false;
2999 }
3000
3001 switch (genMode)
3002 {
3003 case GL_NONE:
3004 if (components != 0)
3005 {
3006 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3007 return false;
3008 }
3009 break;
3010
3011 case GL_OBJECT_LINEAR_CHROMIUM:
3012 case GL_EYE_LINEAR_CHROMIUM:
3013 case GL_CONSTANT_CHROMIUM:
3014 if (components < 1 || components > 4)
3015 {
3016 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3017 return false;
3018 }
3019 if (!coeffs)
3020 {
3021 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3022 return false;
3023 }
3024 break;
3025
3026 default:
3027 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3028 return false;
3029 }
3030
3031 // If the location is -1 then the command is silently ignored
3032 // and no further validation is needed.
3033 if (location == -1)
3034 return true;
3035
3036 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3037
3038 if (!binding.valid)
3039 {
3040 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3041 return false;
3042 }
3043
3044 if (binding.type != GL_NONE)
3045 {
3046 GLint expectedComponents = 0;
3047 switch (binding.type)
3048 {
3049 case GL_FLOAT:
3050 expectedComponents = 1;
3051 break;
3052 case GL_FLOAT_VEC2:
3053 expectedComponents = 2;
3054 break;
3055 case GL_FLOAT_VEC3:
3056 expectedComponents = 3;
3057 break;
3058 case GL_FLOAT_VEC4:
3059 expectedComponents = 4;
3060 break;
3061 default:
3062 context->handleError(Error(GL_INVALID_OPERATION,
3063 "Fragment input type is not a floating point scalar or vector."));
3064 return false;
3065 }
3066 if (expectedComponents != components && genMode != GL_NONE)
3067 {
3068 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3069 return false;
3070 }
3071 }
3072 return true;
3073}
3074
Geoff Lang97073d12016-04-20 10:42:34 -07003075bool ValidateCopyTextureCHROMIUM(Context *context,
3076 GLuint sourceId,
3077 GLuint destId,
3078 GLint internalFormat,
3079 GLenum destType,
3080 GLboolean unpackFlipY,
3081 GLboolean unpackPremultiplyAlpha,
3082 GLboolean unpackUnmultiplyAlpha)
3083{
3084 if (!context->getExtensions().copyTexture)
3085 {
3086 context->handleError(
3087 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3088 return false;
3089 }
3090
3091 const gl::Texture *source = context->getTexture(sourceId);
3092 if (source == nullptr)
3093 {
3094 context->handleError(
3095 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3096 return false;
3097 }
3098
3099 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3100 {
3101 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3102 return false;
3103 }
3104
3105 GLenum sourceTarget = source->getTarget();
3106 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3107 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3108 {
3109 context->handleError(
3110 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3111 return false;
3112 }
3113
3114 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3115 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3116 {
3117 context->handleError(
3118 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3119 return false;
3120 }
3121
3122 const gl::Texture *dest = context->getTexture(destId);
3123 if (dest == nullptr)
3124 {
3125 context->handleError(
3126 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3127 return false;
3128 }
3129
3130 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3131 {
3132 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3133 return false;
3134 }
3135
3136 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3137 {
3138 context->handleError(
3139 Error(GL_INVALID_OPERATION,
3140 "Destination internal format and type combination is not valid."));
3141 return false;
3142 }
3143
3144 if (dest->getImmutableFormat())
3145 {
3146 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3147 return false;
3148 }
3149
3150 return true;
3151}
3152
3153bool ValidateCopySubTextureCHROMIUM(Context *context,
3154 GLuint sourceId,
3155 GLuint destId,
3156 GLint xoffset,
3157 GLint yoffset,
3158 GLint x,
3159 GLint y,
3160 GLsizei width,
3161 GLsizei height,
3162 GLboolean unpackFlipY,
3163 GLboolean unpackPremultiplyAlpha,
3164 GLboolean unpackUnmultiplyAlpha)
3165{
3166 if (!context->getExtensions().copyTexture)
3167 {
3168 context->handleError(
3169 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3170 return false;
3171 }
3172
3173 const gl::Texture *source = context->getTexture(sourceId);
3174 if (source == nullptr)
3175 {
3176 context->handleError(
3177 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3178 return false;
3179 }
3180
3181 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3182 {
3183 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3184 return false;
3185 }
3186
3187 GLenum sourceTarget = source->getTarget();
3188 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3189 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3190 {
3191 context->handleError(
3192 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3193 return false;
3194 }
3195
3196 if (x < 0 || y < 0)
3197 {
3198 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3199 return false;
3200 }
3201
3202 if (width < 0 || height < 0)
3203 {
3204 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3205 return false;
3206 }
3207
3208 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3209 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3210 {
3211 context->handleError(
3212 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3213 return false;
3214 }
3215
3216 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3217 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3218 {
3219 context->handleError(
3220 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3221 return false;
3222 }
3223
3224 const gl::Texture *dest = context->getTexture(destId);
3225 if (dest == nullptr)
3226 {
3227 context->handleError(
3228 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3229 return false;
3230 }
3231
3232 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3233 {
3234 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3235 return false;
3236 }
3237
3238 GLenum destTarget = dest->getTarget();
3239 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3240 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3241 {
3242 context->handleError(
3243 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3244 return false;
3245 }
3246
3247 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3248 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3249 {
3250 context->handleError(
3251 Error(GL_INVALID_OPERATION,
3252 "Destination internal format and type combination is not valid."));
3253 return false;
3254 }
3255
3256 if (xoffset < 0 || yoffset < 0)
3257 {
3258 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3259 return false;
3260 }
3261
3262 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3263 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3264 {
3265 context->handleError(
3266 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3267 return false;
3268 }
3269
3270 return true;
3271}
3272
Martin Radev4c4c8e72016-08-04 12:25:34 +03003273bool ValidateCreateShader(Context *context, GLenum type)
3274{
3275 switch (type)
3276 {
3277 case GL_VERTEX_SHADER:
3278 case GL_FRAGMENT_SHADER:
3279 break;
3280 case GL_COMPUTE_SHADER:
3281 if (context->getGLVersion().isES31())
3282 {
3283 break;
3284 }
3285 default:
3286 context->handleError(Error(GL_INVALID_ENUM));
3287 return false;
3288 }
Jamie Madill29639852016-09-02 15:00:09 -04003289
3290 return true;
3291}
3292
3293bool ValidateBufferData(ValidationContext *context,
3294 GLenum target,
3295 GLsizeiptr size,
3296 const GLvoid *data,
3297 GLenum usage)
3298{
3299 if (size < 0)
3300 {
3301 context->handleError(Error(GL_INVALID_VALUE));
3302 return false;
3303 }
3304
3305 switch (usage)
3306 {
3307 case GL_STREAM_DRAW:
3308 case GL_STATIC_DRAW:
3309 case GL_DYNAMIC_DRAW:
3310 break;
3311
3312 case GL_STREAM_READ:
3313 case GL_STREAM_COPY:
3314 case GL_STATIC_READ:
3315 case GL_STATIC_COPY:
3316 case GL_DYNAMIC_READ:
3317 case GL_DYNAMIC_COPY:
3318 if (context->getClientMajorVersion() < 3)
3319 {
3320 context->handleError(Error(GL_INVALID_ENUM));
3321 return false;
3322 }
3323 break;
3324
3325 default:
3326 context->handleError(Error(GL_INVALID_ENUM));
3327 return false;
3328 }
3329
3330 if (!ValidBufferTarget(context, target))
3331 {
3332 context->handleError(Error(GL_INVALID_ENUM));
3333 return false;
3334 }
3335
3336 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3337
3338 if (!buffer)
3339 {
3340 context->handleError(Error(GL_INVALID_OPERATION));
3341 return false;
3342 }
3343
3344 return true;
3345}
3346
3347bool ValidateBufferSubData(ValidationContext *context,
3348 GLenum target,
3349 GLintptr offset,
3350 GLsizeiptr size,
3351 const GLvoid *data)
3352{
3353 if (size < 0 || offset < 0)
3354 {
3355 context->handleError(Error(GL_INVALID_VALUE));
3356 return false;
3357 }
3358
3359 if (!ValidBufferTarget(context, target))
3360 {
3361 context->handleError(Error(GL_INVALID_ENUM));
3362 return false;
3363 }
3364
3365 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3366
3367 if (!buffer)
3368 {
3369 context->handleError(Error(GL_INVALID_OPERATION));
3370 return false;
3371 }
3372
3373 if (buffer->isMapped())
3374 {
3375 context->handleError(Error(GL_INVALID_OPERATION));
3376 return false;
3377 }
3378
3379 // Check for possible overflow of size + offset
3380 angle::CheckedNumeric<size_t> checkedSize(size);
3381 checkedSize += offset;
3382 if (!checkedSize.IsValid())
3383 {
3384 context->handleError(Error(GL_OUT_OF_MEMORY));
3385 return false;
3386 }
3387
3388 if (size + offset > buffer->getSize())
3389 {
3390 context->handleError(Error(GL_INVALID_VALUE));
3391 return false;
3392 }
3393
Martin Radev4c4c8e72016-08-04 12:25:34 +03003394 return true;
3395}
3396
Geoff Langc287ea62016-09-16 14:46:51 -04003397bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3398{
3399 if (!context->getExtensions().webglCompatibility)
3400 {
3401 context->handleError(
3402 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3403 return false;
3404 }
3405
3406 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3407 auto extension = extensionInfos.find(name);
3408 if (extension == extensionInfos.end() || !extension->second.Enableable)
3409 {
3410 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3411 return false;
3412 }
3413
3414 return true;
3415}
3416
Jamie Madillc29968b2016-01-20 11:17:23 -05003417} // namespace gl