blob: 68285cecfda200e74fce7b52026535291d4a7d35 [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
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001190// check for combinations of format and type that are valid for ReadPixels
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001191bool ValidES2ReadFormatType(ValidationContext *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001192{
1193 switch (format)
1194 {
1195 case GL_RGBA:
1196 switch (type)
1197 {
1198 case GL_UNSIGNED_BYTE:
1199 break;
1200 default:
1201 return false;
1202 }
1203 break;
1204 case GL_BGRA_EXT:
1205 switch (type)
1206 {
1207 case GL_UNSIGNED_BYTE:
1208 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1209 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1210 break;
1211 default:
1212 return false;
1213 }
1214 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001215 case GL_RG_EXT:
1216 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001217 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001218 {
1219 return false;
1220 }
1221 switch (type)
1222 {
1223 case GL_UNSIGNED_BYTE:
1224 break;
1225 default:
1226 return false;
1227 }
1228 break;
1229
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001230 default:
1231 return false;
1232 }
1233 return true;
1234}
1235
Austin Kinross08332632015-05-05 13:35:47 -07001236bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1237 const GLenum *attachments)
1238{
Jamie Madillc29968b2016-01-20 11:17:23 -05001239 if (!context->getExtensions().discardFramebuffer)
1240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001242 return false;
1243 }
1244
Austin Kinross08332632015-05-05 13:35:47 -07001245 bool defaultFramebuffer = false;
1246
1247 switch (target)
1248 {
1249 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001250 defaultFramebuffer =
1251 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1252 break;
Austin Kinross08332632015-05-05 13:35:47 -07001253 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001254 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001255 return false;
1256 }
1257
1258 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1259}
1260
Austin Kinrossbc781f32015-10-26 09:27:38 -07001261bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1262{
1263 if (!context->getExtensions().vertexArrayObject)
1264 {
Jamie Madill437fa652016-05-03 15:13:24 -04001265 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001266 return false;
1267 }
1268
1269 return ValidateBindVertexArrayBase(context, array);
1270}
1271
1272bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1273{
1274 if (!context->getExtensions().vertexArrayObject)
1275 {
Jamie Madill437fa652016-05-03 15:13:24 -04001276 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001277 return false;
1278 }
1279
Olli Etuaho41997e72016-03-10 13:38:39 +02001280 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001281}
1282
1283bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1284{
1285 if (!context->getExtensions().vertexArrayObject)
1286 {
Jamie Madill437fa652016-05-03 15:13:24 -04001287 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001288 return false;
1289 }
1290
Olli Etuaho41997e72016-03-10 13:38:39 +02001291 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001292}
1293
1294bool ValidateIsVertexArrayOES(Context *context)
1295{
1296 if (!context->getExtensions().vertexArrayObject)
1297 {
Jamie Madill437fa652016-05-03 15:13:24 -04001298 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001299 return false;
1300 }
1301
1302 return true;
1303}
Geoff Langc5629752015-12-07 16:29:04 -05001304
1305bool ValidateProgramBinaryOES(Context *context,
1306 GLuint program,
1307 GLenum binaryFormat,
1308 const void *binary,
1309 GLint length)
1310{
1311 if (!context->getExtensions().getProgramBinary)
1312 {
Jamie Madill437fa652016-05-03 15:13:24 -04001313 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001314 return false;
1315 }
1316
1317 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1318}
1319
1320bool ValidateGetProgramBinaryOES(Context *context,
1321 GLuint program,
1322 GLsizei bufSize,
1323 GLsizei *length,
1324 GLenum *binaryFormat,
1325 void *binary)
1326{
1327 if (!context->getExtensions().getProgramBinary)
1328 {
Jamie Madill437fa652016-05-03 15:13:24 -04001329 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001330 return false;
1331 }
1332
1333 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1334}
Geoff Lange102fee2015-12-10 11:23:30 -05001335
Geoff Lang70d0f492015-12-10 17:45:46 -05001336static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1337{
1338 switch (source)
1339 {
1340 case GL_DEBUG_SOURCE_API:
1341 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1342 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1343 case GL_DEBUG_SOURCE_OTHER:
1344 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1345 return !mustBeThirdPartyOrApplication;
1346
1347 case GL_DEBUG_SOURCE_THIRD_PARTY:
1348 case GL_DEBUG_SOURCE_APPLICATION:
1349 return true;
1350
1351 default:
1352 return false;
1353 }
1354}
1355
1356static bool ValidDebugType(GLenum type)
1357{
1358 switch (type)
1359 {
1360 case GL_DEBUG_TYPE_ERROR:
1361 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1362 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1363 case GL_DEBUG_TYPE_PERFORMANCE:
1364 case GL_DEBUG_TYPE_PORTABILITY:
1365 case GL_DEBUG_TYPE_OTHER:
1366 case GL_DEBUG_TYPE_MARKER:
1367 case GL_DEBUG_TYPE_PUSH_GROUP:
1368 case GL_DEBUG_TYPE_POP_GROUP:
1369 return true;
1370
1371 default:
1372 return false;
1373 }
1374}
1375
1376static bool ValidDebugSeverity(GLenum severity)
1377{
1378 switch (severity)
1379 {
1380 case GL_DEBUG_SEVERITY_HIGH:
1381 case GL_DEBUG_SEVERITY_MEDIUM:
1382 case GL_DEBUG_SEVERITY_LOW:
1383 case GL_DEBUG_SEVERITY_NOTIFICATION:
1384 return true;
1385
1386 default:
1387 return false;
1388 }
1389}
1390
Geoff Lange102fee2015-12-10 11:23:30 -05001391bool ValidateDebugMessageControlKHR(Context *context,
1392 GLenum source,
1393 GLenum type,
1394 GLenum severity,
1395 GLsizei count,
1396 const GLuint *ids,
1397 GLboolean enabled)
1398{
1399 if (!context->getExtensions().debug)
1400 {
Jamie Madill437fa652016-05-03 15:13:24 -04001401 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001402 return false;
1403 }
1404
Geoff Lang70d0f492015-12-10 17:45:46 -05001405 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1406 {
Jamie Madill437fa652016-05-03 15:13:24 -04001407 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001408 return false;
1409 }
1410
1411 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1412 {
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001414 return false;
1415 }
1416
1417 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1418 {
Jamie Madill437fa652016-05-03 15:13:24 -04001419 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001420 return false;
1421 }
1422
1423 if (count > 0)
1424 {
1425 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1426 {
Jamie Madill437fa652016-05-03 15:13:24 -04001427 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001428 GL_INVALID_OPERATION,
1429 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1430 return false;
1431 }
1432
1433 if (severity != GL_DONT_CARE)
1434 {
Jamie Madill437fa652016-05-03 15:13:24 -04001435 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001436 Error(GL_INVALID_OPERATION,
1437 "If count is greater than zero, severity must be GL_DONT_CARE."));
1438 return false;
1439 }
1440 }
1441
Geoff Lange102fee2015-12-10 11:23:30 -05001442 return true;
1443}
1444
1445bool ValidateDebugMessageInsertKHR(Context *context,
1446 GLenum source,
1447 GLenum type,
1448 GLuint id,
1449 GLenum severity,
1450 GLsizei length,
1451 const GLchar *buf)
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
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001459 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001460 {
1461 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1462 // not generate an error.
1463 return false;
1464 }
1465
1466 if (!ValidDebugSeverity(severity))
1467 {
Jamie Madill437fa652016-05-03 15:13:24 -04001468 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001469 return false;
1470 }
1471
1472 if (!ValidDebugType(type))
1473 {
Jamie Madill437fa652016-05-03 15:13:24 -04001474 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001475 return false;
1476 }
1477
1478 if (!ValidDebugSource(source, true))
1479 {
Jamie Madill437fa652016-05-03 15:13:24 -04001480 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001481 return false;
1482 }
1483
1484 size_t messageLength = (length < 0) ? strlen(buf) : length;
1485 if (messageLength > context->getExtensions().maxDebugMessageLength)
1486 {
Jamie Madill437fa652016-05-03 15:13:24 -04001487 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001488 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1489 return false;
1490 }
1491
Geoff Lange102fee2015-12-10 11:23:30 -05001492 return true;
1493}
1494
1495bool ValidateDebugMessageCallbackKHR(Context *context,
1496 GLDEBUGPROCKHR callback,
1497 const void *userParam)
1498{
1499 if (!context->getExtensions().debug)
1500 {
Jamie Madill437fa652016-05-03 15:13:24 -04001501 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001502 return false;
1503 }
1504
Geoff Lange102fee2015-12-10 11:23:30 -05001505 return true;
1506}
1507
1508bool ValidateGetDebugMessageLogKHR(Context *context,
1509 GLuint count,
1510 GLsizei bufSize,
1511 GLenum *sources,
1512 GLenum *types,
1513 GLuint *ids,
1514 GLenum *severities,
1515 GLsizei *lengths,
1516 GLchar *messageLog)
1517{
1518 if (!context->getExtensions().debug)
1519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001521 return false;
1522 }
1523
Geoff Lang70d0f492015-12-10 17:45:46 -05001524 if (bufSize < 0 && messageLog != nullptr)
1525 {
Jamie Madill437fa652016-05-03 15:13:24 -04001526 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001527 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1528 return false;
1529 }
1530
Geoff Lange102fee2015-12-10 11:23:30 -05001531 return true;
1532}
1533
1534bool ValidatePushDebugGroupKHR(Context *context,
1535 GLenum source,
1536 GLuint id,
1537 GLsizei length,
1538 const GLchar *message)
1539{
1540 if (!context->getExtensions().debug)
1541 {
Jamie Madill437fa652016-05-03 15:13:24 -04001542 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001543 return false;
1544 }
1545
Geoff Lang70d0f492015-12-10 17:45:46 -05001546 if (!ValidDebugSource(source, true))
1547 {
Jamie Madill437fa652016-05-03 15:13:24 -04001548 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001549 return false;
1550 }
1551
1552 size_t messageLength = (length < 0) ? strlen(message) : length;
1553 if (messageLength > context->getExtensions().maxDebugMessageLength)
1554 {
Jamie Madill437fa652016-05-03 15:13:24 -04001555 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001556 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1557 return false;
1558 }
1559
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001560 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001561 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1562 {
Jamie Madill437fa652016-05-03 15:13:24 -04001563 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001564 Error(GL_STACK_OVERFLOW,
1565 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1566 return false;
1567 }
1568
Geoff Lange102fee2015-12-10 11:23:30 -05001569 return true;
1570}
1571
1572bool ValidatePopDebugGroupKHR(Context *context)
1573{
1574 if (!context->getExtensions().debug)
1575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001577 return false;
1578 }
1579
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001580 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001581 if (currentStackSize <= 1)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001584 return false;
1585 }
1586
1587 return true;
1588}
1589
1590static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1591{
1592 switch (identifier)
1593 {
1594 case GL_BUFFER:
1595 if (context->getBuffer(name) == nullptr)
1596 {
Jamie Madill437fa652016-05-03 15:13:24 -04001597 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001598 return false;
1599 }
1600 return true;
1601
1602 case GL_SHADER:
1603 if (context->getShader(name) == nullptr)
1604 {
Jamie Madill437fa652016-05-03 15:13:24 -04001605 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001606 return false;
1607 }
1608 return true;
1609
1610 case GL_PROGRAM:
1611 if (context->getProgram(name) == nullptr)
1612 {
Jamie Madill437fa652016-05-03 15:13:24 -04001613 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001614 return false;
1615 }
1616 return true;
1617
1618 case GL_VERTEX_ARRAY:
1619 if (context->getVertexArray(name) == nullptr)
1620 {
Jamie Madill437fa652016-05-03 15:13:24 -04001621 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001622 return false;
1623 }
1624 return true;
1625
1626 case GL_QUERY:
1627 if (context->getQuery(name) == nullptr)
1628 {
Jamie Madill437fa652016-05-03 15:13:24 -04001629 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001630 return false;
1631 }
1632 return true;
1633
1634 case GL_TRANSFORM_FEEDBACK:
1635 if (context->getTransformFeedback(name) == nullptr)
1636 {
Jamie Madill437fa652016-05-03 15:13:24 -04001637 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001638 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1639 return false;
1640 }
1641 return true;
1642
1643 case GL_SAMPLER:
1644 if (context->getSampler(name) == nullptr)
1645 {
Jamie Madill437fa652016-05-03 15:13:24 -04001646 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001647 return false;
1648 }
1649 return true;
1650
1651 case GL_TEXTURE:
1652 if (context->getTexture(name) == nullptr)
1653 {
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001655 return false;
1656 }
1657 return true;
1658
1659 case GL_RENDERBUFFER:
1660 if (context->getRenderbuffer(name) == nullptr)
1661 {
Jamie Madill437fa652016-05-03 15:13:24 -04001662 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001663 return false;
1664 }
1665 return true;
1666
1667 case GL_FRAMEBUFFER:
1668 if (context->getFramebuffer(name) == nullptr)
1669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001671 return false;
1672 }
1673 return true;
1674
1675 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001676 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001677 return false;
1678 }
Geoff Lange102fee2015-12-10 11:23:30 -05001679}
1680
Martin Radev9d901792016-07-15 15:58:58 +03001681static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1682{
1683 size_t labelLength = 0;
1684
1685 if (length < 0)
1686 {
1687 if (label != nullptr)
1688 {
1689 labelLength = strlen(label);
1690 }
1691 }
1692 else
1693 {
1694 labelLength = static_cast<size_t>(length);
1695 }
1696
1697 if (labelLength > context->getExtensions().maxLabelLength)
1698 {
1699 context->handleError(
1700 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1701 return false;
1702 }
1703
1704 return true;
1705}
1706
Geoff Lange102fee2015-12-10 11:23:30 -05001707bool ValidateObjectLabelKHR(Context *context,
1708 GLenum identifier,
1709 GLuint name,
1710 GLsizei length,
1711 const GLchar *label)
1712{
1713 if (!context->getExtensions().debug)
1714 {
Jamie Madill437fa652016-05-03 15:13:24 -04001715 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001716 return false;
1717 }
1718
Geoff Lang70d0f492015-12-10 17:45:46 -05001719 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1720 {
1721 return false;
1722 }
1723
Martin Radev9d901792016-07-15 15:58:58 +03001724 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001725 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001726 return false;
1727 }
1728
Geoff Lange102fee2015-12-10 11:23:30 -05001729 return true;
1730}
1731
1732bool ValidateGetObjectLabelKHR(Context *context,
1733 GLenum identifier,
1734 GLuint name,
1735 GLsizei bufSize,
1736 GLsizei *length,
1737 GLchar *label)
1738{
1739 if (!context->getExtensions().debug)
1740 {
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001742 return false;
1743 }
1744
Geoff Lang70d0f492015-12-10 17:45:46 -05001745 if (bufSize < 0)
1746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001748 return false;
1749 }
1750
1751 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1752 {
1753 return false;
1754 }
1755
Martin Radev9d901792016-07-15 15:58:58 +03001756 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001757}
1758
1759static bool ValidateObjectPtrName(Context *context, const void *ptr)
1760{
1761 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1762 {
Jamie Madill437fa652016-05-03 15:13:24 -04001763 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001764 return false;
1765 }
1766
Geoff Lange102fee2015-12-10 11:23:30 -05001767 return true;
1768}
1769
1770bool ValidateObjectPtrLabelKHR(Context *context,
1771 const void *ptr,
1772 GLsizei length,
1773 const GLchar *label)
1774{
1775 if (!context->getExtensions().debug)
1776 {
Jamie Madill437fa652016-05-03 15:13:24 -04001777 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001778 return false;
1779 }
1780
Geoff Lang70d0f492015-12-10 17:45:46 -05001781 if (!ValidateObjectPtrName(context, ptr))
1782 {
1783 return false;
1784 }
1785
Martin Radev9d901792016-07-15 15:58:58 +03001786 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001787 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001788 return false;
1789 }
1790
Geoff Lange102fee2015-12-10 11:23:30 -05001791 return true;
1792}
1793
1794bool ValidateGetObjectPtrLabelKHR(Context *context,
1795 const void *ptr,
1796 GLsizei bufSize,
1797 GLsizei *length,
1798 GLchar *label)
1799{
1800 if (!context->getExtensions().debug)
1801 {
Jamie Madill437fa652016-05-03 15:13:24 -04001802 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001803 return false;
1804 }
1805
Geoff Lang70d0f492015-12-10 17:45:46 -05001806 if (bufSize < 0)
1807 {
Jamie Madill437fa652016-05-03 15:13:24 -04001808 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001809 return false;
1810 }
1811
1812 if (!ValidateObjectPtrName(context, ptr))
1813 {
1814 return false;
1815 }
1816
Martin Radev9d901792016-07-15 15:58:58 +03001817 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001818}
1819
1820bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1821{
1822 if (!context->getExtensions().debug)
1823 {
Jamie Madill437fa652016-05-03 15:13:24 -04001824 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001825 return false;
1826 }
1827
Geoff Lang70d0f492015-12-10 17:45:46 -05001828 // TODO: represent this in Context::getQueryParameterInfo.
1829 switch (pname)
1830 {
1831 case GL_DEBUG_CALLBACK_FUNCTION:
1832 case GL_DEBUG_CALLBACK_USER_PARAM:
1833 break;
1834
1835 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001836 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001837 return false;
1838 }
1839
Geoff Lange102fee2015-12-10 11:23:30 -05001840 return true;
1841}
Jamie Madillc29968b2016-01-20 11:17:23 -05001842
1843bool ValidateBlitFramebufferANGLE(Context *context,
1844 GLint srcX0,
1845 GLint srcY0,
1846 GLint srcX1,
1847 GLint srcY1,
1848 GLint dstX0,
1849 GLint dstY0,
1850 GLint dstX1,
1851 GLint dstY1,
1852 GLbitfield mask,
1853 GLenum filter)
1854{
1855 if (!context->getExtensions().framebufferBlit)
1856 {
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 return false;
1859 }
1860
1861 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1862 {
1863 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001864 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001865 GL_INVALID_OPERATION,
1866 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1867 return false;
1868 }
1869
1870 if (filter == GL_LINEAR)
1871 {
Jamie Madill437fa652016-05-03 15:13:24 -04001872 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001873 return false;
1874 }
1875
Jamie Madill51f40ec2016-06-15 14:06:00 -04001876 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1877 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001878
1879 if (mask & GL_COLOR_BUFFER_BIT)
1880 {
1881 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1882 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1883
1884 if (readColorAttachment && drawColorAttachment)
1885 {
1886 if (!(readColorAttachment->type() == GL_TEXTURE &&
1887 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1888 readColorAttachment->type() != GL_RENDERBUFFER &&
1889 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1890 {
Jamie Madill437fa652016-05-03 15:13:24 -04001891 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001892 return false;
1893 }
1894
Geoff Langa15472a2015-08-11 11:48:03 -04001895 for (size_t drawbufferIdx = 0;
1896 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001897 {
Geoff Langa15472a2015-08-11 11:48:03 -04001898 const FramebufferAttachment *attachment =
1899 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1900 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001901 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001902 if (!(attachment->type() == GL_TEXTURE &&
1903 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1904 attachment->type() != GL_RENDERBUFFER &&
1905 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1906 {
Jamie Madill437fa652016-05-03 15:13:24 -04001907 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 return false;
1909 }
1910
1911 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001912 if (!Format::SameSized(attachment->getFormat(),
1913 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001914 {
Jamie Madill437fa652016-05-03 15:13:24 -04001915 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001916 return false;
1917 }
1918 }
1919 }
1920
Jamie Madill51f40ec2016-06-15 14:06:00 -04001921 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001922 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1923 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001926 return false;
1927 }
1928 }
1929 }
1930
1931 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1932 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1933 for (size_t i = 0; i < 2; i++)
1934 {
1935 if (mask & masks[i])
1936 {
1937 const FramebufferAttachment *readBuffer =
1938 readFramebuffer->getAttachment(attachments[i]);
1939 const FramebufferAttachment *drawBuffer =
1940 drawFramebuffer->getAttachment(attachments[i]);
1941
1942 if (readBuffer && drawBuffer)
1943 {
1944 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1945 dstX0, dstY0, dstX1, dstY1))
1946 {
1947 // only whole-buffer copies are permitted
1948 ERR(
1949 "Only whole-buffer depth and stencil blits are supported by this "
1950 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001951 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001952 return false;
1953 }
1954
1955 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1956 {
Jamie Madill437fa652016-05-03 15:13:24 -04001957 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001958 return false;
1959 }
1960 }
1961 }
1962 }
1963
1964 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1965 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001966}
Jamie Madillc29968b2016-01-20 11:17:23 -05001967
1968bool ValidateClear(ValidationContext *context, GLbitfield mask)
1969{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001970 auto fbo = context->getGLState().getDrawFramebuffer();
1971 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001972 {
Jamie Madill437fa652016-05-03 15:13:24 -04001973 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001974 return false;
1975 }
1976
1977 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1978 {
Jamie Madill437fa652016-05-03 15:13:24 -04001979 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001980 return false;
1981 }
1982
1983 return true;
1984}
1985
1986bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1987{
1988 if (!context->getExtensions().drawBuffers)
1989 {
Jamie Madill437fa652016-05-03 15:13:24 -04001990 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001991 return false;
1992 }
1993
1994 return ValidateDrawBuffersBase(context, n, bufs);
1995}
1996
Jamie Madill73a84962016-02-12 09:27:23 -05001997bool ValidateTexImage2D(Context *context,
1998 GLenum target,
1999 GLint level,
2000 GLint internalformat,
2001 GLsizei width,
2002 GLsizei height,
2003 GLint border,
2004 GLenum format,
2005 GLenum type,
2006 const GLvoid *pixels)
2007{
Martin Radev1be913c2016-07-11 17:59:16 +03002008 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002009 {
2010 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2011 0, 0, width, height, border, format, type, pixels);
2012 }
2013
Martin Radev1be913c2016-07-11 17:59:16 +03002014 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002015 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2016 0, 0, width, height, 1, border, format, type, pixels);
2017}
2018
2019bool ValidateTexSubImage2D(Context *context,
2020 GLenum target,
2021 GLint level,
2022 GLint xoffset,
2023 GLint yoffset,
2024 GLsizei width,
2025 GLsizei height,
2026 GLenum format,
2027 GLenum type,
2028 const GLvoid *pixels)
2029{
2030
Martin Radev1be913c2016-07-11 17:59:16 +03002031 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002032 {
2033 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2034 yoffset, width, height, 0, format, type, pixels);
2035 }
2036
Martin Radev1be913c2016-07-11 17:59:16 +03002037 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002038 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2039 yoffset, 0, width, height, 1, 0, format, type, pixels);
2040}
2041
2042bool ValidateCompressedTexImage2D(Context *context,
2043 GLenum target,
2044 GLint level,
2045 GLenum internalformat,
2046 GLsizei width,
2047 GLsizei height,
2048 GLint border,
2049 GLsizei imageSize,
2050 const GLvoid *data)
2051{
Martin Radev1be913c2016-07-11 17:59:16 +03002052 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002053 {
2054 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
2055 0, width, height, border, GL_NONE, GL_NONE, data))
2056 {
2057 return false;
2058 }
2059 }
2060 else
2061 {
Martin Radev1be913c2016-07-11 17:59:16 +03002062 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002063 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
2064 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
2065 data))
2066 {
2067 return false;
2068 }
2069 }
2070
2071 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002072 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002073 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002074 if (blockSizeOrErr.isError())
2075 {
2076 context->handleError(blockSizeOrErr.getError());
2077 return false;
2078 }
2079
2080 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002083 return false;
2084 }
2085
2086 return true;
2087}
2088
2089bool ValidateCompressedTexSubImage2D(Context *context,
2090 GLenum target,
2091 GLint level,
2092 GLint xoffset,
2093 GLint yoffset,
2094 GLsizei width,
2095 GLsizei height,
2096 GLenum format,
2097 GLsizei imageSize,
2098 const GLvoid *data)
2099{
Martin Radev1be913c2016-07-11 17:59:16 +03002100 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002101 {
2102 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2103 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2104 {
2105 return false;
2106 }
2107 }
2108 else
2109 {
Martin Radev1be913c2016-07-11 17:59:16 +03002110 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002111 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2112 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2113 data))
2114 {
2115 return false;
2116 }
2117 }
2118
2119 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002120 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002121 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002122 if (blockSizeOrErr.isError())
2123 {
2124 context->handleError(blockSizeOrErr.getError());
2125 return false;
2126 }
2127
2128 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002129 {
Jamie Madill437fa652016-05-03 15:13:24 -04002130 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002131 return false;
2132 }
2133
2134 return true;
2135}
2136
Olli Etuaho4f667482016-03-30 15:56:35 +03002137bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2138{
2139 if (!context->getExtensions().mapBuffer)
2140 {
Jamie Madill437fa652016-05-03 15:13:24 -04002141 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002142 return false;
2143 }
2144
2145 return ValidateGetBufferPointervBase(context, target, pname, params);
2146}
2147
2148bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2149{
2150 if (!context->getExtensions().mapBuffer)
2151 {
Jamie Madill437fa652016-05-03 15:13:24 -04002152 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002153 return false;
2154 }
2155
2156 if (!ValidBufferTarget(context, target))
2157 {
Jamie Madill437fa652016-05-03 15:13:24 -04002158 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002159 return false;
2160 }
2161
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002162 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002163
2164 if (buffer == nullptr)
2165 {
Jamie Madill437fa652016-05-03 15:13:24 -04002166 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002167 return false;
2168 }
2169
2170 if (access != GL_WRITE_ONLY_OES)
2171 {
Jamie Madill437fa652016-05-03 15:13:24 -04002172 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002173 return false;
2174 }
2175
2176 if (buffer->isMapped())
2177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002179 return false;
2180 }
2181
2182 return true;
2183}
2184
2185bool ValidateUnmapBufferOES(Context *context, GLenum target)
2186{
2187 if (!context->getExtensions().mapBuffer)
2188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002190 return false;
2191 }
2192
2193 return ValidateUnmapBufferBase(context, target);
2194}
2195
2196bool ValidateMapBufferRangeEXT(Context *context,
2197 GLenum target,
2198 GLintptr offset,
2199 GLsizeiptr length,
2200 GLbitfield access)
2201{
2202 if (!context->getExtensions().mapBufferRange)
2203 {
Jamie Madill437fa652016-05-03 15:13:24 -04002204 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002205 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2206 return false;
2207 }
2208
2209 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2210}
2211
2212bool ValidateFlushMappedBufferRangeEXT(Context *context,
2213 GLenum target,
2214 GLintptr offset,
2215 GLsizeiptr length)
2216{
2217 if (!context->getExtensions().mapBufferRange)
2218 {
Jamie Madill437fa652016-05-03 15:13:24 -04002219 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002220 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2221 return false;
2222 }
2223
2224 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2225}
2226
Ian Ewell54f87462016-03-10 13:47:21 -05002227bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2228{
2229 Texture *textureObject = context->getTexture(texture);
2230 if (textureObject && textureObject->getTarget() != target && texture != 0)
2231 {
Jamie Madill437fa652016-05-03 15:13:24 -04002232 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002233 return false;
2234 }
2235
2236 switch (target)
2237 {
2238 case GL_TEXTURE_2D:
2239 case GL_TEXTURE_CUBE_MAP:
2240 break;
2241
2242 case GL_TEXTURE_3D:
2243 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002244 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002245 {
Jamie Madill437fa652016-05-03 15:13:24 -04002246 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002247 return false;
2248 }
2249 break;
2250 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002251 if (!context->getExtensions().eglImageExternal &&
2252 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002253 {
Jamie Madill437fa652016-05-03 15:13:24 -04002254 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002255 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2256 return false;
2257 }
2258 break;
2259 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002260 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002261 return false;
2262 }
2263
2264 return true;
2265}
2266
Geoff Langd8605522016-04-13 10:19:12 -04002267bool ValidateBindUniformLocationCHROMIUM(Context *context,
2268 GLuint program,
2269 GLint location,
2270 const GLchar *name)
2271{
2272 if (!context->getExtensions().bindUniformLocation)
2273 {
Jamie Madill437fa652016-05-03 15:13:24 -04002274 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002275 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2276 return false;
2277 }
2278
2279 Program *programObject = GetValidProgram(context, program);
2280 if (!programObject)
2281 {
2282 return false;
2283 }
2284
2285 if (location < 0)
2286 {
Jamie Madill437fa652016-05-03 15:13:24 -04002287 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002288 return false;
2289 }
2290
2291 const Caps &caps = context->getCaps();
2292 if (static_cast<size_t>(location) >=
2293 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2294 {
Jamie Madill437fa652016-05-03 15:13:24 -04002295 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002296 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2297 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2298 return false;
2299 }
2300
2301 if (strncmp(name, "gl_", 3) == 0)
2302 {
Jamie Madill437fa652016-05-03 15:13:24 -04002303 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002304 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2305 return false;
2306 }
2307
2308 return true;
2309}
2310
Jamie Madille2e406c2016-06-02 13:04:10 -04002311bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002312{
2313 if (!context->getExtensions().framebufferMixedSamples)
2314 {
2315 context->handleError(
2316 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2317 return false;
2318 }
2319 switch (components)
2320 {
2321 case GL_RGB:
2322 case GL_RGBA:
2323 case GL_ALPHA:
2324 case GL_NONE:
2325 break;
2326 default:
2327 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002328 Error(GL_INVALID_ENUM,
2329 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002330 return false;
2331 }
2332
2333 return true;
2334}
2335
Sami Väisänene45e53b2016-05-25 10:36:04 +03002336// CHROMIUM_path_rendering
2337
2338bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2339{
2340 if (!context->getExtensions().pathRendering)
2341 {
2342 context->handleError(
2343 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2344 return false;
2345 }
2346 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2347 {
2348 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2349 return false;
2350 }
2351 if (matrix == nullptr)
2352 {
2353 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2354 return false;
2355 }
2356 return true;
2357}
2358
2359bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2360{
2361 if (!context->getExtensions().pathRendering)
2362 {
2363 context->handleError(
2364 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2365 return false;
2366 }
2367 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2368 {
2369 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2370 return false;
2371 }
2372 return true;
2373}
2374
2375bool ValidateGenPaths(Context *context, GLsizei range)
2376{
2377 if (!context->getExtensions().pathRendering)
2378 {
2379 context->handleError(
2380 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2381 return false;
2382 }
2383
2384 // range = 0 is undefined in NV_path_rendering.
2385 // we add stricter semantic check here and require a non zero positive range.
2386 if (range <= 0)
2387 {
2388 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2389 return false;
2390 }
2391
2392 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2393 {
2394 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2395 return false;
2396 }
2397
2398 return true;
2399}
2400
2401bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2402{
2403 if (!context->getExtensions().pathRendering)
2404 {
2405 context->handleError(
2406 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2407 return false;
2408 }
2409
2410 // range = 0 is undefined in NV_path_rendering.
2411 // we add stricter semantic check here and require a non zero positive range.
2412 if (range <= 0)
2413 {
2414 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2415 return false;
2416 }
2417
2418 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2419 checkedRange += range;
2420
2421 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2422 {
2423 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2424 return false;
2425 }
2426 return true;
2427}
2428
2429bool ValidatePathCommands(Context *context,
2430 GLuint path,
2431 GLsizei numCommands,
2432 const GLubyte *commands,
2433 GLsizei numCoords,
2434 GLenum coordType,
2435 const void *coords)
2436{
2437 if (!context->getExtensions().pathRendering)
2438 {
2439 context->handleError(
2440 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2441 return false;
2442 }
2443 if (!context->hasPath(path))
2444 {
2445 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2446 return false;
2447 }
2448
2449 if (numCommands < 0)
2450 {
2451 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2452 return false;
2453 }
2454 else if (numCommands > 0)
2455 {
2456 if (!commands)
2457 {
2458 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2459 return false;
2460 }
2461 }
2462
2463 if (numCoords < 0)
2464 {
2465 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2466 return false;
2467 }
2468 else if (numCoords > 0)
2469 {
2470 if (!coords)
2471 {
2472 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2473 return false;
2474 }
2475 }
2476
2477 std::uint32_t coordTypeSize = 0;
2478 switch (coordType)
2479 {
2480 case GL_BYTE:
2481 coordTypeSize = sizeof(GLbyte);
2482 break;
2483
2484 case GL_UNSIGNED_BYTE:
2485 coordTypeSize = sizeof(GLubyte);
2486 break;
2487
2488 case GL_SHORT:
2489 coordTypeSize = sizeof(GLshort);
2490 break;
2491
2492 case GL_UNSIGNED_SHORT:
2493 coordTypeSize = sizeof(GLushort);
2494 break;
2495
2496 case GL_FLOAT:
2497 coordTypeSize = sizeof(GLfloat);
2498 break;
2499
2500 default:
2501 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2502 return false;
2503 }
2504
2505 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2506 checkedSize += (coordTypeSize * numCoords);
2507 if (!checkedSize.IsValid())
2508 {
2509 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2510 return false;
2511 }
2512
2513 // early return skips command data validation when it doesn't exist.
2514 if (!commands)
2515 return true;
2516
2517 GLsizei expectedNumCoords = 0;
2518 for (GLsizei i = 0; i < numCommands; ++i)
2519 {
2520 switch (commands[i])
2521 {
2522 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2523 break;
2524 case GL_MOVE_TO_CHROMIUM:
2525 case GL_LINE_TO_CHROMIUM:
2526 expectedNumCoords += 2;
2527 break;
2528 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2529 expectedNumCoords += 4;
2530 break;
2531 case GL_CUBIC_CURVE_TO_CHROMIUM:
2532 expectedNumCoords += 6;
2533 break;
2534 case GL_CONIC_CURVE_TO_CHROMIUM:
2535 expectedNumCoords += 5;
2536 break;
2537 default:
2538 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2539 return false;
2540 }
2541 }
2542 if (expectedNumCoords != numCoords)
2543 {
2544 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2545 return false;
2546 }
2547
2548 return true;
2549}
2550
2551bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2552{
2553 if (!context->getExtensions().pathRendering)
2554 {
2555 context->handleError(
2556 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2557 return false;
2558 }
2559 if (!context->hasPath(path))
2560 {
2561 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2562 return false;
2563 }
2564
2565 switch (pname)
2566 {
2567 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2568 if (value < 0.0f)
2569 {
2570 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2571 return false;
2572 }
2573 break;
2574 case GL_PATH_END_CAPS_CHROMIUM:
2575 switch (static_cast<GLenum>(value))
2576 {
2577 case GL_FLAT_CHROMIUM:
2578 case GL_SQUARE_CHROMIUM:
2579 case GL_ROUND_CHROMIUM:
2580 break;
2581 default:
2582 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2583 return false;
2584 }
2585 break;
2586 case GL_PATH_JOIN_STYLE_CHROMIUM:
2587 switch (static_cast<GLenum>(value))
2588 {
2589 case GL_MITER_REVERT_CHROMIUM:
2590 case GL_BEVEL_CHROMIUM:
2591 case GL_ROUND_CHROMIUM:
2592 break;
2593 default:
2594 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2595 return false;
2596 }
2597 case GL_PATH_MITER_LIMIT_CHROMIUM:
2598 if (value < 0.0f)
2599 {
2600 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2601 return false;
2602 }
2603 break;
2604
2605 case GL_PATH_STROKE_BOUND_CHROMIUM:
2606 // no errors, only clamping.
2607 break;
2608
2609 default:
2610 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2611 return false;
2612 }
2613 return true;
2614}
2615
2616bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2617{
2618 if (!context->getExtensions().pathRendering)
2619 {
2620 context->handleError(
2621 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2622 return false;
2623 }
2624
2625 if (!context->hasPath(path))
2626 {
2627 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2628 return false;
2629 }
2630 if (!value)
2631 {
2632 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2633 return false;
2634 }
2635
2636 switch (pname)
2637 {
2638 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2639 case GL_PATH_END_CAPS_CHROMIUM:
2640 case GL_PATH_JOIN_STYLE_CHROMIUM:
2641 case GL_PATH_MITER_LIMIT_CHROMIUM:
2642 case GL_PATH_STROKE_BOUND_CHROMIUM:
2643 break;
2644
2645 default:
2646 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2647 return false;
2648 }
2649
2650 return true;
2651}
2652
2653bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2654{
2655 if (!context->getExtensions().pathRendering)
2656 {
2657 context->handleError(
2658 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2659 return false;
2660 }
2661
2662 switch (func)
2663 {
2664 case GL_NEVER:
2665 case GL_ALWAYS:
2666 case GL_LESS:
2667 case GL_LEQUAL:
2668 case GL_EQUAL:
2669 case GL_GEQUAL:
2670 case GL_GREATER:
2671 case GL_NOTEQUAL:
2672 break;
2673 default:
2674 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2675 return false;
2676 }
2677
2678 return true;
2679}
2680
2681// Note that the spec specifies that for the path drawing commands
2682// if the path object is not an existing path object the command
2683// does nothing and no error is generated.
2684// However if the path object exists but has not been specified any
2685// commands then an error is generated.
2686
2687bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2688{
2689 if (!context->getExtensions().pathRendering)
2690 {
2691 context->handleError(
2692 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2693 return false;
2694 }
2695 if (context->hasPath(path) && !context->hasPathData(path))
2696 {
2697 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2698 return false;
2699 }
2700
2701 switch (fillMode)
2702 {
2703 case GL_COUNT_UP_CHROMIUM:
2704 case GL_COUNT_DOWN_CHROMIUM:
2705 break;
2706 default:
2707 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2708 return false;
2709 }
2710
2711 if (!isPow2(mask + 1))
2712 {
2713 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2714 return false;
2715 }
2716
2717 return true;
2718}
2719
2720bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2721{
2722 if (!context->getExtensions().pathRendering)
2723 {
2724 context->handleError(
2725 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2726 return false;
2727 }
2728 if (context->hasPath(path) && !context->hasPathData(path))
2729 {
2730 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2731 return false;
2732 }
2733
2734 return true;
2735}
2736
2737bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2738{
2739 if (!context->getExtensions().pathRendering)
2740 {
2741 context->handleError(
2742 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2743 return false;
2744 }
2745 if (context->hasPath(path) && !context->hasPathData(path))
2746 {
2747 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2748 return false;
2749 }
2750
2751 switch (coverMode)
2752 {
2753 case GL_CONVEX_HULL_CHROMIUM:
2754 case GL_BOUNDING_BOX_CHROMIUM:
2755 break;
2756 default:
2757 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2758 return false;
2759 }
2760 return true;
2761}
2762
2763bool ValidateStencilThenCoverFillPath(Context *context,
2764 GLuint path,
2765 GLenum fillMode,
2766 GLuint mask,
2767 GLenum coverMode)
2768{
2769 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2770 ValidateCoverPath(context, path, coverMode);
2771}
2772
2773bool ValidateStencilThenCoverStrokePath(Context *context,
2774 GLuint path,
2775 GLint reference,
2776 GLuint mask,
2777 GLenum coverMode)
2778{
2779 return ValidateStencilStrokePath(context, path, reference, mask) &&
2780 ValidateCoverPath(context, path, coverMode);
2781}
2782
2783bool ValidateIsPath(Context *context)
2784{
2785 if (!context->getExtensions().pathRendering)
2786 {
2787 context->handleError(
2788 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2789 return false;
2790 }
2791 return true;
2792}
2793
Sami Väisänend59ca052016-06-21 16:10:00 +03002794bool ValidateCoverFillPathInstanced(Context *context,
2795 GLsizei numPaths,
2796 GLenum pathNameType,
2797 const void *paths,
2798 GLuint pathBase,
2799 GLenum coverMode,
2800 GLenum transformType,
2801 const GLfloat *transformValues)
2802{
2803 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2804 transformType, transformValues))
2805 return false;
2806
2807 switch (coverMode)
2808 {
2809 case GL_CONVEX_HULL_CHROMIUM:
2810 case GL_BOUNDING_BOX_CHROMIUM:
2811 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2812 break;
2813 default:
2814 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2815 return false;
2816 }
2817
2818 return true;
2819}
2820
2821bool ValidateCoverStrokePathInstanced(Context *context,
2822 GLsizei numPaths,
2823 GLenum pathNameType,
2824 const void *paths,
2825 GLuint pathBase,
2826 GLenum coverMode,
2827 GLenum transformType,
2828 const GLfloat *transformValues)
2829{
2830 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2831 transformType, transformValues))
2832 return false;
2833
2834 switch (coverMode)
2835 {
2836 case GL_CONVEX_HULL_CHROMIUM:
2837 case GL_BOUNDING_BOX_CHROMIUM:
2838 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2839 break;
2840 default:
2841 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2842 return false;
2843 }
2844
2845 return true;
2846}
2847
2848bool ValidateStencilFillPathInstanced(Context *context,
2849 GLsizei numPaths,
2850 GLenum pathNameType,
2851 const void *paths,
2852 GLuint pathBase,
2853 GLenum fillMode,
2854 GLuint mask,
2855 GLenum transformType,
2856 const GLfloat *transformValues)
2857{
2858
2859 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2860 transformType, transformValues))
2861 return false;
2862
2863 switch (fillMode)
2864 {
2865 case GL_COUNT_UP_CHROMIUM:
2866 case GL_COUNT_DOWN_CHROMIUM:
2867 break;
2868 default:
2869 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2870 return false;
2871 }
2872 if (!isPow2(mask + 1))
2873 {
2874 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2875 return false;
2876 }
2877 return true;
2878}
2879
2880bool ValidateStencilStrokePathInstanced(Context *context,
2881 GLsizei numPaths,
2882 GLenum pathNameType,
2883 const void *paths,
2884 GLuint pathBase,
2885 GLint reference,
2886 GLuint mask,
2887 GLenum transformType,
2888 const GLfloat *transformValues)
2889{
2890 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2891 transformType, transformValues))
2892 return false;
2893
2894 // no more validation here.
2895
2896 return true;
2897}
2898
2899bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2900 GLsizei numPaths,
2901 GLenum pathNameType,
2902 const void *paths,
2903 GLuint pathBase,
2904 GLenum fillMode,
2905 GLuint mask,
2906 GLenum coverMode,
2907 GLenum transformType,
2908 const GLfloat *transformValues)
2909{
2910 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2911 transformType, transformValues))
2912 return false;
2913
2914 switch (coverMode)
2915 {
2916 case GL_CONVEX_HULL_CHROMIUM:
2917 case GL_BOUNDING_BOX_CHROMIUM:
2918 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2919 break;
2920 default:
2921 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2922 return false;
2923 }
2924
2925 switch (fillMode)
2926 {
2927 case GL_COUNT_UP_CHROMIUM:
2928 case GL_COUNT_DOWN_CHROMIUM:
2929 break;
2930 default:
2931 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2932 return false;
2933 }
2934 if (!isPow2(mask + 1))
2935 {
2936 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2937 return false;
2938 }
2939
2940 return true;
2941}
2942
2943bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2944 GLsizei numPaths,
2945 GLenum pathNameType,
2946 const void *paths,
2947 GLuint pathBase,
2948 GLint reference,
2949 GLuint mask,
2950 GLenum coverMode,
2951 GLenum transformType,
2952 const GLfloat *transformValues)
2953{
2954 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2955 transformType, transformValues))
2956 return false;
2957
2958 switch (coverMode)
2959 {
2960 case GL_CONVEX_HULL_CHROMIUM:
2961 case GL_BOUNDING_BOX_CHROMIUM:
2962 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2963 break;
2964 default:
2965 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2966 return false;
2967 }
2968
2969 return true;
2970}
2971
Sami Väisänen46eaa942016-06-29 10:26:37 +03002972bool ValidateBindFragmentInputLocation(Context *context,
2973 GLuint program,
2974 GLint location,
2975 const GLchar *name)
2976{
2977 if (!context->getExtensions().pathRendering)
2978 {
2979 context->handleError(
2980 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2981 return false;
2982 }
2983
2984 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2985 if (location >= MaxLocation)
2986 {
2987 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2988 return false;
2989 }
2990
2991 const auto *programObject = context->getProgram(program);
2992 if (!programObject)
2993 {
2994 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2995 return false;
2996 }
2997
2998 if (!name)
2999 {
3000 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3001 return false;
3002 }
3003
3004 if (angle::BeginsWith(name, "gl_"))
3005 {
3006 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3007 return false;
3008 }
3009
3010 return true;
3011}
3012
3013bool ValidateProgramPathFragmentInputGen(Context *context,
3014 GLuint program,
3015 GLint location,
3016 GLenum genMode,
3017 GLint components,
3018 const GLfloat *coeffs)
3019{
3020 if (!context->getExtensions().pathRendering)
3021 {
3022 context->handleError(
3023 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3024 return false;
3025 }
3026
3027 const auto *programObject = context->getProgram(program);
3028 if (!programObject || programObject->isFlaggedForDeletion())
3029 {
3030 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3031 return false;
3032 }
3033
3034 if (!programObject->isLinked())
3035 {
3036 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3037 return false;
3038 }
3039
3040 switch (genMode)
3041 {
3042 case GL_NONE:
3043 if (components != 0)
3044 {
3045 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3046 return false;
3047 }
3048 break;
3049
3050 case GL_OBJECT_LINEAR_CHROMIUM:
3051 case GL_EYE_LINEAR_CHROMIUM:
3052 case GL_CONSTANT_CHROMIUM:
3053 if (components < 1 || components > 4)
3054 {
3055 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3056 return false;
3057 }
3058 if (!coeffs)
3059 {
3060 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3061 return false;
3062 }
3063 break;
3064
3065 default:
3066 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3067 return false;
3068 }
3069
3070 // If the location is -1 then the command is silently ignored
3071 // and no further validation is needed.
3072 if (location == -1)
3073 return true;
3074
3075 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3076
3077 if (!binding.valid)
3078 {
3079 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3080 return false;
3081 }
3082
3083 if (binding.type != GL_NONE)
3084 {
3085 GLint expectedComponents = 0;
3086 switch (binding.type)
3087 {
3088 case GL_FLOAT:
3089 expectedComponents = 1;
3090 break;
3091 case GL_FLOAT_VEC2:
3092 expectedComponents = 2;
3093 break;
3094 case GL_FLOAT_VEC3:
3095 expectedComponents = 3;
3096 break;
3097 case GL_FLOAT_VEC4:
3098 expectedComponents = 4;
3099 break;
3100 default:
3101 context->handleError(Error(GL_INVALID_OPERATION,
3102 "Fragment input type is not a floating point scalar or vector."));
3103 return false;
3104 }
3105 if (expectedComponents != components && genMode != GL_NONE)
3106 {
3107 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3108 return false;
3109 }
3110 }
3111 return true;
3112}
3113
Geoff Lang97073d12016-04-20 10:42:34 -07003114bool ValidateCopyTextureCHROMIUM(Context *context,
3115 GLuint sourceId,
3116 GLuint destId,
3117 GLint internalFormat,
3118 GLenum destType,
3119 GLboolean unpackFlipY,
3120 GLboolean unpackPremultiplyAlpha,
3121 GLboolean unpackUnmultiplyAlpha)
3122{
3123 if (!context->getExtensions().copyTexture)
3124 {
3125 context->handleError(
3126 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3127 return false;
3128 }
3129
3130 const gl::Texture *source = context->getTexture(sourceId);
3131 if (source == nullptr)
3132 {
3133 context->handleError(
3134 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3135 return false;
3136 }
3137
3138 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3139 {
3140 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3141 return false;
3142 }
3143
3144 GLenum sourceTarget = source->getTarget();
3145 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3146 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3147 {
3148 context->handleError(
3149 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3150 return false;
3151 }
3152
3153 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3154 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3155 {
3156 context->handleError(
3157 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3158 return false;
3159 }
3160
3161 const gl::Texture *dest = context->getTexture(destId);
3162 if (dest == nullptr)
3163 {
3164 context->handleError(
3165 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3166 return false;
3167 }
3168
3169 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3170 {
3171 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3172 return false;
3173 }
3174
3175 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3176 {
3177 context->handleError(
3178 Error(GL_INVALID_OPERATION,
3179 "Destination internal format and type combination is not valid."));
3180 return false;
3181 }
3182
3183 if (dest->getImmutableFormat())
3184 {
3185 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3186 return false;
3187 }
3188
3189 return true;
3190}
3191
3192bool ValidateCopySubTextureCHROMIUM(Context *context,
3193 GLuint sourceId,
3194 GLuint destId,
3195 GLint xoffset,
3196 GLint yoffset,
3197 GLint x,
3198 GLint y,
3199 GLsizei width,
3200 GLsizei height,
3201 GLboolean unpackFlipY,
3202 GLboolean unpackPremultiplyAlpha,
3203 GLboolean unpackUnmultiplyAlpha)
3204{
3205 if (!context->getExtensions().copyTexture)
3206 {
3207 context->handleError(
3208 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3209 return false;
3210 }
3211
3212 const gl::Texture *source = context->getTexture(sourceId);
3213 if (source == nullptr)
3214 {
3215 context->handleError(
3216 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3217 return false;
3218 }
3219
3220 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3221 {
3222 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3223 return false;
3224 }
3225
3226 GLenum sourceTarget = source->getTarget();
3227 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3228 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3229 {
3230 context->handleError(
3231 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3232 return false;
3233 }
3234
3235 if (x < 0 || y < 0)
3236 {
3237 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3238 return false;
3239 }
3240
3241 if (width < 0 || height < 0)
3242 {
3243 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3244 return false;
3245 }
3246
3247 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3248 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3249 {
3250 context->handleError(
3251 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3252 return false;
3253 }
3254
3255 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3256 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3257 {
3258 context->handleError(
3259 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3260 return false;
3261 }
3262
3263 const gl::Texture *dest = context->getTexture(destId);
3264 if (dest == nullptr)
3265 {
3266 context->handleError(
3267 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3268 return false;
3269 }
3270
3271 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3272 {
3273 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3274 return false;
3275 }
3276
3277 GLenum destTarget = dest->getTarget();
3278 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3279 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3280 {
3281 context->handleError(
3282 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3283 return false;
3284 }
3285
3286 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3287 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3288 {
3289 context->handleError(
3290 Error(GL_INVALID_OPERATION,
3291 "Destination internal format and type combination is not valid."));
3292 return false;
3293 }
3294
3295 if (xoffset < 0 || yoffset < 0)
3296 {
3297 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3298 return false;
3299 }
3300
3301 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3302 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3303 {
3304 context->handleError(
3305 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3306 return false;
3307 }
3308
3309 return true;
3310}
3311
Martin Radev4c4c8e72016-08-04 12:25:34 +03003312bool ValidateCreateShader(Context *context, GLenum type)
3313{
3314 switch (type)
3315 {
3316 case GL_VERTEX_SHADER:
3317 case GL_FRAGMENT_SHADER:
3318 break;
3319 case GL_COMPUTE_SHADER:
3320 if (context->getGLVersion().isES31())
3321 {
3322 break;
3323 }
3324 default:
3325 context->handleError(Error(GL_INVALID_ENUM));
3326 return false;
3327 }
Jamie Madill29639852016-09-02 15:00:09 -04003328
3329 return true;
3330}
3331
3332bool ValidateBufferData(ValidationContext *context,
3333 GLenum target,
3334 GLsizeiptr size,
3335 const GLvoid *data,
3336 GLenum usage)
3337{
3338 if (size < 0)
3339 {
3340 context->handleError(Error(GL_INVALID_VALUE));
3341 return false;
3342 }
3343
3344 switch (usage)
3345 {
3346 case GL_STREAM_DRAW:
3347 case GL_STATIC_DRAW:
3348 case GL_DYNAMIC_DRAW:
3349 break;
3350
3351 case GL_STREAM_READ:
3352 case GL_STREAM_COPY:
3353 case GL_STATIC_READ:
3354 case GL_STATIC_COPY:
3355 case GL_DYNAMIC_READ:
3356 case GL_DYNAMIC_COPY:
3357 if (context->getClientMajorVersion() < 3)
3358 {
3359 context->handleError(Error(GL_INVALID_ENUM));
3360 return false;
3361 }
3362 break;
3363
3364 default:
3365 context->handleError(Error(GL_INVALID_ENUM));
3366 return false;
3367 }
3368
3369 if (!ValidBufferTarget(context, target))
3370 {
3371 context->handleError(Error(GL_INVALID_ENUM));
3372 return false;
3373 }
3374
3375 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3376
3377 if (!buffer)
3378 {
3379 context->handleError(Error(GL_INVALID_OPERATION));
3380 return false;
3381 }
3382
3383 return true;
3384}
3385
3386bool ValidateBufferSubData(ValidationContext *context,
3387 GLenum target,
3388 GLintptr offset,
3389 GLsizeiptr size,
3390 const GLvoid *data)
3391{
3392 if (size < 0 || offset < 0)
3393 {
3394 context->handleError(Error(GL_INVALID_VALUE));
3395 return false;
3396 }
3397
3398 if (!ValidBufferTarget(context, target))
3399 {
3400 context->handleError(Error(GL_INVALID_ENUM));
3401 return false;
3402 }
3403
3404 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3405
3406 if (!buffer)
3407 {
3408 context->handleError(Error(GL_INVALID_OPERATION));
3409 return false;
3410 }
3411
3412 if (buffer->isMapped())
3413 {
3414 context->handleError(Error(GL_INVALID_OPERATION));
3415 return false;
3416 }
3417
3418 // Check for possible overflow of size + offset
3419 angle::CheckedNumeric<size_t> checkedSize(size);
3420 checkedSize += offset;
3421 if (!checkedSize.IsValid())
3422 {
3423 context->handleError(Error(GL_OUT_OF_MEMORY));
3424 return false;
3425 }
3426
3427 if (size + offset > buffer->getSize())
3428 {
3429 context->handleError(Error(GL_INVALID_VALUE));
3430 return false;
3431 }
3432
Martin Radev4c4c8e72016-08-04 12:25:34 +03003433 return true;
3434}
3435
Geoff Langc287ea62016-09-16 14:46:51 -04003436bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3437{
3438 if (!context->getExtensions().webglCompatibility)
3439 {
3440 context->handleError(
3441 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3442 return false;
3443 }
3444
3445 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3446 auto extension = extensionInfos.find(name);
3447 if (extension == extensionInfos.end() || !extension->second.Enableable)
3448 {
3449 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3450 return false;
3451 }
3452
3453 return true;
3454}
3455
Jamie Madillc29968b2016-01-20 11:17:23 -05003456} // namespace gl