blob: 228f4a7601e6dbbc7086fade86f24fd93232dc4f [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 Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
Jamie Madillef300b12016-10-07 15:12:09 -040017#include "libANGLE/Framebuffer.h"
18#include "libANGLE/FramebufferAttachment.h"
19#include "libANGLE/Renderbuffer.h"
20#include "libANGLE/Shader.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Texture.h"
Jamie Madillef300b12016-10-07 15:12:09 -040022#include "libANGLE/Uniform.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/VertexArray.h"
Jamie Madillef300b12016-10-07 15:12:09 -040024#include "libANGLE/formatutils.h"
25#include "libANGLE/validationES.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28namespace gl
29{
30
Jamie Madillc29968b2016-01-20 11:17:23 -050031namespace
32{
33
34bool IsPartialBlit(gl::Context *context,
35 const FramebufferAttachment *readBuffer,
36 const FramebufferAttachment *writeBuffer,
37 GLint srcX0,
38 GLint srcY0,
39 GLint srcX1,
40 GLint srcY1,
41 GLint dstX0,
42 GLint dstY0,
43 GLint dstX1,
44 GLint dstY1)
45{
46 const Extents &writeSize = writeBuffer->getSize();
47 const Extents &readSize = readBuffer->getSize();
48
49 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
50 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
51 {
52 return true;
53 }
54
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050056 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070057 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050058 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
59 scissor.height < writeSize.height;
60 }
61
62 return false;
63}
64
Sami Väisänend59ca052016-06-21 16:10:00 +030065template <typename T>
66bool ValidatePathInstances(gl::Context *context,
67 GLsizei numPaths,
68 const void *paths,
69 GLuint pathBase)
70{
71 const auto *array = static_cast<const T *>(paths);
72
73 for (GLsizei i = 0; i < numPaths; ++i)
74 {
75 const GLuint pathName = array[i] + pathBase;
76 if (context->hasPath(pathName) && !context->hasPathData(pathName))
77 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050078 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänend59ca052016-06-21 16:10:00 +030079 return false;
80 }
81 }
82 return true;
83}
84
85bool ValidateInstancedPathParameters(gl::Context *context,
86 GLsizei numPaths,
87 GLenum pathNameType,
88 const void *paths,
89 GLuint pathBase,
90 GLenum transformType,
91 const GLfloat *transformValues)
92{
93 if (!context->getExtensions().pathRendering)
94 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050095 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänend59ca052016-06-21 16:10:00 +030096 return false;
97 }
98
99 if (paths == nullptr)
100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500101 context->handleError(InvalidValue() << "No path name array.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300102 return false;
103 }
104
105 if (numPaths < 0)
106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500107 context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300108 return false;
109 }
110
111 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500113 context->handleError(InvalidOperation() << "Overflow in numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300114 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:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500159 context->handleError(InvalidEnum() << "Invalid path name type.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300160 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:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500187 context->handleError(InvalidEnum() << "Invalid transformation.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300188 return false;
189 }
190 if (componentCount != 0 && transformValues == nullptr)
191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500192 context->handleError(InvalidValue() << "No transform array given.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300193 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500201 context->handleError(InvalidOperation() << "Overflow in num paths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300202 return false;
203 }
204
205 return true;
206}
207
Geoff Lang4f0e0032017-05-01 16:04:35 -0400208bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
Geoff Lang97073d12016-04-20 10:42:34 -0700209{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400210 // Table 1.1 from the CHROMIUM_copy_texture spec
Geoff Langca271392017-04-05 12:30:00 -0400211 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700212 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400213 case GL_RED:
Geoff Lang97073d12016-04-20 10:42:34 -0700214 case GL_ALPHA:
215 case GL_LUMINANCE:
216 case GL_LUMINANCE_ALPHA:
217 case GL_RGB:
218 case GL_RGBA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400219 case GL_RGB8:
220 case GL_RGBA8:
221 case GL_BGRA_EXT:
222 case GL_BGRA8_EXT:
Geoff Lang97073d12016-04-20 10:42:34 -0700223 return true;
224
Geoff Lang4f0e0032017-05-01 16:04:35 -0400225 default:
226 return false;
227 }
228}
Geoff Lang97073d12016-04-20 10:42:34 -0700229
Geoff Lang4f0e0032017-05-01 16:04:35 -0400230bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
231{
232 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
233}
234
Geoff Lang4f0e0032017-05-01 16:04:35 -0400235bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
236{
237 // Table 1.0 from the CHROMIUM_copy_texture spec
238 switch (internalFormat)
239 {
240 case GL_RGB:
241 case GL_RGBA:
242 case GL_RGB8:
243 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700244 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400245 case GL_BGRA8_EXT:
246 case GL_SRGB_EXT:
247 case GL_SRGB_ALPHA_EXT:
248 case GL_R8:
249 case GL_R8UI:
250 case GL_RG8:
251 case GL_RG8UI:
252 case GL_SRGB8:
253 case GL_RGB565:
254 case GL_RGB8UI:
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400255 case GL_RGB10_A2:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400256 case GL_SRGB8_ALPHA8:
257 case GL_RGB5_A1:
258 case GL_RGBA4:
259 case GL_RGBA8UI:
260 case GL_RGB9_E5:
261 case GL_R16F:
262 case GL_R32F:
263 case GL_RG16F:
264 case GL_RG32F:
265 case GL_RGB16F:
266 case GL_RGB32F:
267 case GL_RGBA16F:
268 case GL_RGBA32F:
269 case GL_R11F_G11F_B10F:
270 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700271
272 default:
273 return false;
274 }
275}
276
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400277bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
278{
279 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
280}
281
Geoff Lang97073d12016-04-20 10:42:34 -0700282bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
283{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400284 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700285 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400286 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700287 }
288
Geoff Lang4f0e0032017-05-01 16:04:35 -0400289 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
290 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700291 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400292 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700293 }
294
295 return true;
296}
297
Geoff Lang4f0e0032017-05-01 16:04:35 -0400298bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700299{
300 switch (target)
301 {
302 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400303 return textureType == GL_TEXTURE_2D;
304
305 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
306 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
307 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
308 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
309 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
310 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
311 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700312
313 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
314 // supported
315
316 default:
317 return false;
318 }
319}
320
321bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
322{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400323 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700324 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400325 case GL_TEXTURE_2D:
326 return true;
327
328 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
329 // supported
330
331 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
332 // supported
333
334 default:
335 return false;
336 }
337}
338
339bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
340{
341 if (level < 0)
342 {
343 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700344 }
345
Geoff Lang4f0e0032017-05-01 16:04:35 -0400346 if (level > 0 && context->getClientVersion() < ES_3_0)
347 {
348 return false;
349 }
Geoff Lang97073d12016-04-20 10:42:34 -0700350
Geoff Lang4f0e0032017-05-01 16:04:35 -0400351 return true;
352}
353
354bool IsValidCopyTextureDestinationLevel(Context *context,
355 GLenum target,
356 GLint level,
357 GLsizei width,
358 GLsizei height)
359{
360 if (level < 0)
361 {
362 return false;
363 }
364
Geoff Lang4f0e0032017-05-01 16:04:35 -0400365 const Caps &caps = context->getCaps();
366 if (target == GL_TEXTURE_2D)
367 {
368 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
369 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
370 {
371 return false;
372 }
373 }
374 else if (IsCubeMapTextureTarget(target))
375 {
376 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
377 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
378 {
379 return false;
380 }
381 }
382
383 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700384}
385
Jamie Madillc1d770e2017-04-13 17:31:24 -0400386bool IsValidStencilFunc(GLenum func)
387{
388 switch (func)
389 {
390 case GL_NEVER:
391 case GL_ALWAYS:
392 case GL_LESS:
393 case GL_LEQUAL:
394 case GL_EQUAL:
395 case GL_GEQUAL:
396 case GL_GREATER:
397 case GL_NOTEQUAL:
398 return true;
399
400 default:
401 return false;
402 }
403}
404
405bool IsValidStencilFace(GLenum face)
406{
407 switch (face)
408 {
409 case GL_FRONT:
410 case GL_BACK:
411 case GL_FRONT_AND_BACK:
412 return true;
413
414 default:
415 return false;
416 }
417}
418
419bool IsValidStencilOp(GLenum op)
420{
421 switch (op)
422 {
423 case GL_ZERO:
424 case GL_KEEP:
425 case GL_REPLACE:
426 case GL_INCR:
427 case GL_DECR:
428 case GL_INVERT:
429 case GL_INCR_WRAP:
430 case GL_DECR_WRAP:
431 return true;
432
433 default:
434 return false;
435 }
436}
437
Jamie Madillbe849e42017-05-02 15:49:00 -0400438bool ValidateES2CopyTexImageParameters(ValidationContext *context,
439 GLenum target,
440 GLint level,
441 GLenum internalformat,
442 bool isSubImage,
443 GLint xoffset,
444 GLint yoffset,
445 GLint x,
446 GLint y,
447 GLsizei width,
448 GLsizei height,
449 GLint border)
450{
451 if (!ValidTexture2DDestinationTarget(context, target))
452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500453 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -0400454 return false;
455 }
456
457 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500459 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400460 return false;
461 }
462
463 Format textureFormat = Format::Invalid();
464 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
465 xoffset, yoffset, 0, x, y, width, height, border,
466 &textureFormat))
467 {
468 return false;
469 }
470
471 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
472 GLenum colorbufferFormat =
473 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
474 const auto &formatInfo = *textureFormat.info;
475
476 // [OpenGL ES 2.0.24] table 3.9
477 if (isSubImage)
478 {
479 switch (formatInfo.format)
480 {
481 case GL_ALPHA:
482 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400483 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
484 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500486 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400487 return false;
488 }
489 break;
490 case GL_LUMINANCE:
491 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
492 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
493 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400494 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
495 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500497 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400498 return false;
499 }
500 break;
501 case GL_RED_EXT:
502 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
503 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
504 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
505 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
506 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400507 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
508 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500510 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400511 return false;
512 }
513 break;
514 case GL_RG_EXT:
515 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
516 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
517 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
518 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400519 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
520 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500522 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400523 return false;
524 }
525 break;
526 case GL_RGB:
527 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
528 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
529 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400530 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
531 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500533 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400534 return false;
535 }
536 break;
537 case GL_LUMINANCE_ALPHA:
538 case GL_RGBA:
539 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400540 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
541 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500543 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400544 return false;
545 }
546 break;
547 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
548 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
549 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
550 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
551 case GL_ETC1_RGB8_OES:
552 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
553 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
554 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
555 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
556 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500557 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400558 return false;
559 case GL_DEPTH_COMPONENT:
560 case GL_DEPTH_STENCIL_OES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500561 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 return false;
563 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500564 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400565 return false;
566 }
567
568 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500570 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400571 return false;
572 }
573 }
574 else
575 {
576 switch (internalformat)
577 {
578 case GL_ALPHA:
579 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
580 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
581 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500583 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400584 return false;
585 }
586 break;
587 case GL_LUMINANCE:
588 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
589 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
590 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
591 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
592 colorbufferFormat != GL_BGR5_A1_ANGLEX)
593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500594 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400595 return false;
596 }
597 break;
598 case GL_RED_EXT:
599 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
600 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
601 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
602 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
603 colorbufferFormat != GL_BGR5_A1_ANGLEX)
604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500605 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400606 return false;
607 }
608 break;
609 case GL_RG_EXT:
610 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
611 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
612 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
613 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500615 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400616 return false;
617 }
618 break;
619 case GL_RGB:
620 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
621 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
622 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
623 colorbufferFormat != GL_BGR5_A1_ANGLEX)
624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500625 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400626 return false;
627 }
628 break;
629 case GL_LUMINANCE_ALPHA:
630 case GL_RGBA:
631 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
632 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
633 colorbufferFormat != GL_BGR5_A1_ANGLEX)
634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500635 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400636 return false;
637 }
638 break;
639 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
640 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
641 if (context->getExtensions().textureCompressionDXT1)
642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500643 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400644 return false;
645 }
646 else
647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500648 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400649 return false;
650 }
651 break;
652 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
653 if (context->getExtensions().textureCompressionDXT3)
654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500655 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400656 return false;
657 }
658 else
659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500660 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400661 return false;
662 }
663 break;
664 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
665 if (context->getExtensions().textureCompressionDXT5)
666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500667 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400668 return false;
669 }
670 else
671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500672 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400673 return false;
674 }
675 break;
676 case GL_ETC1_RGB8_OES:
677 if (context->getExtensions().compressedETC1RGB8Texture)
678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500679 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400680 return false;
681 }
682 else
683 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500684 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400685 return false;
686 }
687 break;
688 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
689 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
690 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
691 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
692 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
693 if (context->getExtensions().lossyETCDecode)
694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500695 context->handleError(InvalidOperation()
696 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400697 return false;
698 }
699 else
700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500701 context->handleError(InvalidEnum()
702 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 return false;
704 }
705 break;
706 case GL_DEPTH_COMPONENT:
707 case GL_DEPTH_COMPONENT16:
708 case GL_DEPTH_COMPONENT32_OES:
709 case GL_DEPTH_STENCIL_OES:
710 case GL_DEPTH24_STENCIL8_OES:
711 if (context->getExtensions().depthTextures)
712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500713 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400714 return false;
715 }
716 else
717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500718 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400719 return false;
720 }
721 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500722 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725 }
726
727 // If width or height is zero, it is a no-op. Return false without setting an error.
728 return (width > 0 && height > 0);
729}
730
731bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
732{
733 switch (cap)
734 {
735 // EXT_multisample_compatibility
736 case GL_MULTISAMPLE_EXT:
737 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
738 return context->getExtensions().multisampleCompatibility;
739
740 case GL_CULL_FACE:
741 case GL_POLYGON_OFFSET_FILL:
742 case GL_SAMPLE_ALPHA_TO_COVERAGE:
743 case GL_SAMPLE_COVERAGE:
744 case GL_SCISSOR_TEST:
745 case GL_STENCIL_TEST:
746 case GL_DEPTH_TEST:
747 case GL_BLEND:
748 case GL_DITHER:
749 return true;
750
751 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
752 case GL_RASTERIZER_DISCARD:
753 return (context->getClientMajorVersion() >= 3);
754
755 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
756 case GL_DEBUG_OUTPUT:
757 return context->getExtensions().debug;
758
759 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
760 return queryOnly && context->getExtensions().bindGeneratesResource;
761
762 case GL_CLIENT_ARRAYS_ANGLE:
763 return queryOnly && context->getExtensions().clientArrays;
764
765 case GL_FRAMEBUFFER_SRGB_EXT:
766 return context->getExtensions().sRGBWriteControl;
767
768 case GL_SAMPLE_MASK:
769 return context->getClientVersion() >= Version(3, 1);
770
771 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
772 return queryOnly && context->getExtensions().robustResourceInitialization;
773
774 default:
775 return false;
776 }
777}
778
Geoff Langfc32e8b2017-05-31 14:16:59 -0400779// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
780// 3.1.
Geoff Langa71a98e2017-06-19 15:15:00 -0400781bool IsValidESSLCharacter(unsigned char c, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400782{
783 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langa71a98e2017-06-19 15:15:00 -0400784 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' &&
785 (allowBackslash || c != '\\') && c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400786 {
787 return true;
788 }
789
790 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
791 if (c >= 9 && c <= 13)
792 {
793 return true;
794 }
795
796 return false;
797}
798
Geoff Langa71a98e2017-06-19 15:15:00 -0400799bool IsValidESSLString(const char *str, size_t len, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400800{
Geoff Langa71a98e2017-06-19 15:15:00 -0400801 for (size_t i = 0; i < len; i++)
802 {
803 if (!IsValidESSLCharacter(str[i], allowBackslash))
804 {
805 return false;
806 }
807 }
808
809 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400810}
811
Jamie Madillc29968b2016-01-20 11:17:23 -0500812} // anonymous namespace
813
Geoff Langff5b2d52016-09-07 11:32:23 -0400814bool ValidateES2TexImageParameters(Context *context,
815 GLenum target,
816 GLint level,
817 GLenum internalformat,
818 bool isCompressed,
819 bool isSubImage,
820 GLint xoffset,
821 GLint yoffset,
822 GLsizei width,
823 GLsizei height,
824 GLint border,
825 GLenum format,
826 GLenum type,
827 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400828 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829{
Jamie Madill6f38f822014-06-06 17:12:20 -0400830 if (!ValidTexture2DDestinationTarget(context, target))
831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500832 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400833 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400834 }
835
Austin Kinross08528e12015-10-07 16:24:40 -0700836 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500838 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400839 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400840 }
841
He Yunchaoced53ae2016-11-29 15:00:51 +0800842 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 std::numeric_limits<GLsizei>::max() - yoffset < height)
844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500845 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400846 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 }
848
Geoff Lang6e898aa2017-06-02 11:17:26 -0400849 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
850 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
851 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
852 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
853 // case.
854 bool nonEqualFormatsAllowed =
855 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
856 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
857
858 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500860 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400861 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400862 }
863
Geoff Langaae65a42014-05-26 12:43:44 -0400864 const gl::Caps &caps = context->getCaps();
865
Geoff Langa9be0dc2014-12-17 12:34:40 -0500866 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400867 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500868 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
869 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500871 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500872 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400873 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500874 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500875 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500876 {
877 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500879 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500880 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400881 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400882
Geoff Langa9be0dc2014-12-17 12:34:40 -0500883 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
884 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500886 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500887 return false;
888 }
889 }
890 else
891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500892 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400893 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894 }
895
He Yunchaoced53ae2016-11-29 15:00:51 +0800896 gl::Texture *texture =
897 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400898 if (!texture)
899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500900 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400901 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902 }
903
Geoff Langa9be0dc2014-12-17 12:34:40 -0500904 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905 {
Geoff Langca271392017-04-05 12:30:00 -0400906 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
907 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500909 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500910 return false;
911 }
912
Geoff Langa9be0dc2014-12-17 12:34:40 -0500913 if (format != GL_NONE)
914 {
Geoff Langca271392017-04-05 12:30:00 -0400915 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
916 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500918 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500919 return false;
920 }
921 }
922
923 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
924 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500926 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500927 return false;
928 }
929 }
930 else
931 {
Geoff Lang69cce582015-09-17 13:20:36 -0400932 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500934 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500935 return false;
936 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 }
938
939 // Verify zero border
940 if (border != 0)
941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500942 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944 }
945
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400946 if (isCompressed)
947 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400948 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400949 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
950 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 switch (actualInternalFormat)
952 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800953 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
954 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
955 if (!context->getExtensions().textureCompressionDXT1)
956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500957 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800958 return false;
959 }
960 break;
961 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
962 if (!context->getExtensions().textureCompressionDXT1)
963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500964 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800965 return false;
966 }
967 break;
968 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
969 if (!context->getExtensions().textureCompressionDXT5)
970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500971 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800972 return false;
973 }
974 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800975 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
976 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
977 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
978 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
979 if (!context->getExtensions().textureCompressionS3TCsRGB)
980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500981 context->handleError(InvalidEnum());
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800982 return false;
983 }
984 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 case GL_ETC1_RGB8_OES:
986 if (!context->getExtensions().compressedETC1RGB8Texture)
987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500988 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800989 return false;
990 }
991 break;
992 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800993 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
994 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
995 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
996 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 if (!context->getExtensions().lossyETCDecode)
998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500999 context->handleError(InvalidEnum()
1000 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001001 return false;
1002 }
1003 break;
1004 default:
1005 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 InvalidEnum()
1007 << "internalformat is not a supported compressed internal format");
Geoff Langb1196682014-07-23 13:47:29 -04001008 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001009 }
Geoff Lang966c9402017-04-18 12:38:27 -04001010
1011 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001012 {
Geoff Lang966c9402017-04-18 12:38:27 -04001013 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1014 height, texture->getWidth(target, level),
1015 texture->getHeight(target, level)))
1016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001018 return false;
1019 }
1020
1021 if (format != actualInternalFormat)
1022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001023 context->handleError(InvalidOperation()
1024 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -04001025 return false;
1026 }
1027 }
1028 else
1029 {
1030 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001032 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001033 return false;
1034 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 }
1036 }
1037 else
1038 {
1039 // validate <type> by itself (used as secondary key below)
1040 switch (type)
1041 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001042 case GL_UNSIGNED_BYTE:
1043 case GL_UNSIGNED_SHORT_5_6_5:
1044 case GL_UNSIGNED_SHORT_4_4_4_4:
1045 case GL_UNSIGNED_SHORT_5_5_5_1:
1046 case GL_UNSIGNED_SHORT:
1047 case GL_UNSIGNED_INT:
1048 case GL_UNSIGNED_INT_24_8_OES:
1049 case GL_HALF_FLOAT_OES:
1050 case GL_FLOAT:
1051 break;
1052 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001053 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 }
1056
1057 // validate <format> + <type> combinations
1058 // - invalid <format> -> sets INVALID_ENUM
1059 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1060 switch (format)
1061 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001062 case GL_ALPHA:
1063 case GL_LUMINANCE:
1064 case GL_LUMINANCE_ALPHA:
1065 switch (type)
1066 {
1067 case GL_UNSIGNED_BYTE:
1068 case GL_FLOAT:
1069 case GL_HALF_FLOAT_OES:
1070 break;
1071 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001072 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001073 return false;
1074 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001075 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001076 case GL_RED:
1077 case GL_RG:
1078 if (!context->getExtensions().textureRG)
1079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001080 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001081 return false;
1082 }
1083 switch (type)
1084 {
1085 case GL_UNSIGNED_BYTE:
1086 case GL_FLOAT:
1087 case GL_HALF_FLOAT_OES:
1088 break;
1089 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001090 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 return false;
1092 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001094 case GL_RGB:
1095 switch (type)
1096 {
1097 case GL_UNSIGNED_BYTE:
1098 case GL_UNSIGNED_SHORT_5_6_5:
1099 case GL_FLOAT:
1100 case GL_HALF_FLOAT_OES:
1101 break;
1102 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001103 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001104 return false;
1105 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001107 case GL_RGBA:
1108 switch (type)
1109 {
1110 case GL_UNSIGNED_BYTE:
1111 case GL_UNSIGNED_SHORT_4_4_4_4:
1112 case GL_UNSIGNED_SHORT_5_5_5_1:
1113 case GL_FLOAT:
1114 case GL_HALF_FLOAT_OES:
1115 break;
1116 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001117 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 return false;
1119 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001121 case GL_BGRA_EXT:
1122 switch (type)
1123 {
1124 case GL_UNSIGNED_BYTE:
1125 break;
1126 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001127 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 return false;
1129 }
1130 break;
1131 case GL_SRGB_EXT:
1132 case GL_SRGB_ALPHA_EXT:
1133 if (!context->getExtensions().sRGB)
1134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001135 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 return false;
1137 }
1138 switch (type)
1139 {
1140 case GL_UNSIGNED_BYTE:
1141 break;
1142 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001143 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001144 return false;
1145 }
1146 break;
1147 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1148 // handled below
1149 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1150 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1151 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1152 break;
1153 case GL_DEPTH_COMPONENT:
1154 switch (type)
1155 {
1156 case GL_UNSIGNED_SHORT:
1157 case GL_UNSIGNED_INT:
1158 break;
1159 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001160 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001161 return false;
1162 }
1163 break;
1164 case GL_DEPTH_STENCIL_OES:
1165 switch (type)
1166 {
1167 case GL_UNSIGNED_INT_24_8_OES:
1168 break;
1169 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001171 return false;
1172 }
1173 break;
1174 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001175 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001176 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001177 }
1178
1179 switch (format)
1180 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001181 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1182 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1183 if (context->getExtensions().textureCompressionDXT1)
1184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001185 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001186 return false;
1187 }
1188 else
1189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001190 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001191 return false;
1192 }
1193 break;
1194 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1195 if (context->getExtensions().textureCompressionDXT3)
1196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001197 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001198 return false;
1199 }
1200 else
1201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001202 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 return false;
1204 }
1205 break;
1206 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1207 if (context->getExtensions().textureCompressionDXT5)
1208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001209 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
1211 }
1212 else
1213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001214 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001215 return false;
1216 }
1217 break;
1218 case GL_ETC1_RGB8_OES:
1219 if (context->getExtensions().compressedETC1RGB8Texture)
1220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001221 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 return false;
1223 }
1224 else
1225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001226 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001227 return false;
1228 }
1229 break;
1230 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001231 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1232 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1233 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1234 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001235 if (context->getExtensions().lossyETCDecode)
1236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001237 context->handleError(InvalidOperation()
1238 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001239 return false;
1240 }
1241 else
1242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001243 context->handleError(InvalidEnum()
1244 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001245 return false;
1246 }
1247 break;
1248 case GL_DEPTH_COMPONENT:
1249 case GL_DEPTH_STENCIL_OES:
1250 if (!context->getExtensions().depthTextures)
1251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001253 return false;
1254 }
1255 if (target != GL_TEXTURE_2D)
1256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001257 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001258 return false;
1259 }
1260 // OES_depth_texture supports loading depth data and multiple levels,
1261 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001262 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001264 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001265 return false;
1266 }
1267 break;
1268 default:
1269 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
Geoff Lang6e898aa2017-06-02 11:17:26 -04001272 if (!isSubImage)
1273 {
1274 switch (internalformat)
1275 {
1276 case GL_RGBA32F:
1277 if (!context->getExtensions().colorBufferFloatRGBA)
1278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidValue()
1280 << "Sized GL_RGBA32F internal format requires "
1281 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001282 return false;
1283 }
1284 if (type != GL_FLOAT)
1285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001286 context->handleError(InvalidOperation()
1287 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001288 return false;
1289 }
1290 if (format != GL_RGBA)
1291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001292 context->handleError(InvalidOperation()
1293 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001294 return false;
1295 }
1296 break;
1297
1298 case GL_RGB32F:
1299 if (!context->getExtensions().colorBufferFloatRGB)
1300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001301 context->handleError(InvalidValue()
1302 << "Sized GL_RGB32F internal format requires "
1303 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001304 return false;
1305 }
1306 if (type != GL_FLOAT)
1307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001308 context->handleError(InvalidOperation()
1309 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001310 return false;
1311 }
1312 if (format != GL_RGB)
1313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001314 context->handleError(InvalidOperation()
1315 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001316 return false;
1317 }
1318 break;
1319
1320 default:
1321 break;
1322 }
1323 }
1324
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 if (type == GL_FLOAT)
1326 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001327 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001329 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001330 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 }
1332 }
1333 else if (type == GL_HALF_FLOAT_OES)
1334 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001335 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 }
1340 }
1341 }
1342
Geoff Langdbcced82017-06-06 15:55:54 -04001343 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1344 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001345 imageSize))
1346 {
1347 return false;
1348 }
1349
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 return true;
1351}
1352
He Yunchaoced53ae2016-11-29 15:00:51 +08001353bool ValidateES2TexStorageParameters(Context *context,
1354 GLenum target,
1355 GLsizei levels,
1356 GLenum internalformat,
1357 GLsizei width,
1358 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359{
1360 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001362 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364 }
1365
1366 if (width < 1 || height < 1 || levels < 1)
1367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
1371
1372 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001375 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 }
1377
1378 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001380 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001381 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 }
1383
Geoff Langca271392017-04-05 12:30:00 -04001384 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001385 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001388 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
1390
Geoff Langaae65a42014-05-26 12:43:44 -04001391 const gl::Caps &caps = context->getCaps();
1392
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 switch (target)
1394 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001395 case GL_TEXTURE_2D:
1396 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1397 static_cast<GLuint>(height) > caps.max2DTextureSize)
1398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 return false;
1401 }
1402 break;
1403 case GL_TEXTURE_CUBE_MAP:
1404 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1405 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 return false;
1409 }
1410 break;
1411 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 }
1415
Geoff Langc0b9ef42014-07-02 10:02:37 -04001416 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
1418 if (!gl::isPow2(width) || !gl::isPow2(height))
1419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001420 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 }
1423 }
1424
1425 switch (internalformat)
1426 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001427 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1428 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1429 if (!context->getExtensions().textureCompressionDXT1)
1430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001432 return false;
1433 }
1434 break;
1435 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1436 if (!context->getExtensions().textureCompressionDXT3)
1437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001438 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001439 return false;
1440 }
1441 break;
1442 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1443 if (!context->getExtensions().textureCompressionDXT5)
1444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001446 return false;
1447 }
1448 break;
1449 case GL_ETC1_RGB8_OES:
1450 if (!context->getExtensions().compressedETC1RGB8Texture)
1451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001453 return false;
1454 }
1455 break;
1456 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001457 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1458 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1459 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1460 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 if (!context->getExtensions().lossyETCDecode)
1462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001463 context->handleError(InvalidEnum()
1464 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001465 return false;
1466 }
1467 break;
1468 case GL_RGBA32F_EXT:
1469 case GL_RGB32F_EXT:
1470 case GL_ALPHA32F_EXT:
1471 case GL_LUMINANCE32F_EXT:
1472 case GL_LUMINANCE_ALPHA32F_EXT:
1473 if (!context->getExtensions().textureFloat)
1474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001475 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001476 return false;
1477 }
1478 break;
1479 case GL_RGBA16F_EXT:
1480 case GL_RGB16F_EXT:
1481 case GL_ALPHA16F_EXT:
1482 case GL_LUMINANCE16F_EXT:
1483 case GL_LUMINANCE_ALPHA16F_EXT:
1484 if (!context->getExtensions().textureHalfFloat)
1485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001486 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001487 return false;
1488 }
1489 break;
1490 case GL_R8_EXT:
1491 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001492 if (!context->getExtensions().textureRG)
1493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001494 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001495 return false;
1496 }
1497 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 case GL_R16F_EXT:
1499 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001500 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001503 return false;
1504 }
1505 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001506 case GL_R32F_EXT:
1507 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001508 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001511 return false;
1512 }
1513 break;
1514 case GL_DEPTH_COMPONENT16:
1515 case GL_DEPTH_COMPONENT32_OES:
1516 case GL_DEPTH24_STENCIL8_OES:
1517 if (!context->getExtensions().depthTextures)
1518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001519 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001520 return false;
1521 }
1522 if (target != GL_TEXTURE_2D)
1523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001524 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001525 return false;
1526 }
1527 // ANGLE_depth_texture only supports 1-level textures
1528 if (levels != 1)
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001531 return false;
1532 }
1533 break;
1534 default:
1535 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001536 }
1537
Geoff Lang691e58c2014-12-19 17:03:25 -05001538 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 if (!texture || texture->id() == 0)
1540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001542 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001543 }
1544
Geoff Lang69cce582015-09-17 13:20:36 -04001545 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001548 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001549 }
1550
1551 return true;
1552}
1553
He Yunchaoced53ae2016-11-29 15:00:51 +08001554bool ValidateDiscardFramebufferEXT(Context *context,
1555 GLenum target,
1556 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001557 const GLenum *attachments)
1558{
Jamie Madillc29968b2016-01-20 11:17:23 -05001559 if (!context->getExtensions().discardFramebuffer)
1560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001561 context->handleError(InvalidOperation() << "Extension not enabled");
Jamie Madillc29968b2016-01-20 11:17:23 -05001562 return false;
1563 }
1564
Austin Kinross08332632015-05-05 13:35:47 -07001565 bool defaultFramebuffer = false;
1566
1567 switch (target)
1568 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001569 case GL_FRAMEBUFFER:
1570 defaultFramebuffer =
1571 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1572 break;
1573 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001574 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001575 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001576 }
1577
He Yunchaoced53ae2016-11-29 15:00:51 +08001578 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1579 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001580}
1581
Austin Kinrossbc781f32015-10-26 09:27:38 -07001582bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1583{
1584 if (!context->getExtensions().vertexArrayObject)
1585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001586 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001587 return false;
1588 }
1589
1590 return ValidateBindVertexArrayBase(context, array);
1591}
1592
1593bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1594{
1595 if (!context->getExtensions().vertexArrayObject)
1596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001598 return false;
1599 }
1600
Olli Etuaho41997e72016-03-10 13:38:39 +02001601 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001602}
1603
1604bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1605{
1606 if (!context->getExtensions().vertexArrayObject)
1607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001608 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001609 return false;
1610 }
1611
Olli Etuaho41997e72016-03-10 13:38:39 +02001612 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001613}
1614
1615bool ValidateIsVertexArrayOES(Context *context)
1616{
1617 if (!context->getExtensions().vertexArrayObject)
1618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001619 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001620 return false;
1621 }
1622
1623 return true;
1624}
Geoff Langc5629752015-12-07 16:29:04 -05001625
1626bool ValidateProgramBinaryOES(Context *context,
1627 GLuint program,
1628 GLenum binaryFormat,
1629 const void *binary,
1630 GLint length)
1631{
1632 if (!context->getExtensions().getProgramBinary)
1633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001634 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001635 return false;
1636 }
1637
1638 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1639}
1640
1641bool ValidateGetProgramBinaryOES(Context *context,
1642 GLuint program,
1643 GLsizei bufSize,
1644 GLsizei *length,
1645 GLenum *binaryFormat,
1646 void *binary)
1647{
1648 if (!context->getExtensions().getProgramBinary)
1649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001650 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001651 return false;
1652 }
1653
1654 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1655}
Geoff Lange102fee2015-12-10 11:23:30 -05001656
Geoff Lang70d0f492015-12-10 17:45:46 -05001657static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1658{
1659 switch (source)
1660 {
1661 case GL_DEBUG_SOURCE_API:
1662 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1663 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1664 case GL_DEBUG_SOURCE_OTHER:
1665 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1666 return !mustBeThirdPartyOrApplication;
1667
1668 case GL_DEBUG_SOURCE_THIRD_PARTY:
1669 case GL_DEBUG_SOURCE_APPLICATION:
1670 return true;
1671
1672 default:
1673 return false;
1674 }
1675}
1676
1677static bool ValidDebugType(GLenum type)
1678{
1679 switch (type)
1680 {
1681 case GL_DEBUG_TYPE_ERROR:
1682 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1683 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1684 case GL_DEBUG_TYPE_PERFORMANCE:
1685 case GL_DEBUG_TYPE_PORTABILITY:
1686 case GL_DEBUG_TYPE_OTHER:
1687 case GL_DEBUG_TYPE_MARKER:
1688 case GL_DEBUG_TYPE_PUSH_GROUP:
1689 case GL_DEBUG_TYPE_POP_GROUP:
1690 return true;
1691
1692 default:
1693 return false;
1694 }
1695}
1696
1697static bool ValidDebugSeverity(GLenum severity)
1698{
1699 switch (severity)
1700 {
1701 case GL_DEBUG_SEVERITY_HIGH:
1702 case GL_DEBUG_SEVERITY_MEDIUM:
1703 case GL_DEBUG_SEVERITY_LOW:
1704 case GL_DEBUG_SEVERITY_NOTIFICATION:
1705 return true;
1706
1707 default:
1708 return false;
1709 }
1710}
1711
Geoff Lange102fee2015-12-10 11:23:30 -05001712bool ValidateDebugMessageControlKHR(Context *context,
1713 GLenum source,
1714 GLenum type,
1715 GLenum severity,
1716 GLsizei count,
1717 const GLuint *ids,
1718 GLboolean enabled)
1719{
1720 if (!context->getExtensions().debug)
1721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001722 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001723 return false;
1724 }
1725
Geoff Lang70d0f492015-12-10 17:45:46 -05001726 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001728 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001729 return false;
1730 }
1731
1732 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001734 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001735 return false;
1736 }
1737
1738 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001740 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001741 return false;
1742 }
1743
1744 if (count > 0)
1745 {
1746 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(
1749 InvalidOperation()
1750 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001751 return false;
1752 }
1753
1754 if (severity != GL_DONT_CARE)
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001757 InvalidOperation()
1758 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001759 return false;
1760 }
1761 }
1762
Geoff Lange102fee2015-12-10 11:23:30 -05001763 return true;
1764}
1765
1766bool ValidateDebugMessageInsertKHR(Context *context,
1767 GLenum source,
1768 GLenum type,
1769 GLuint id,
1770 GLenum severity,
1771 GLsizei length,
1772 const GLchar *buf)
1773{
1774 if (!context->getExtensions().debug)
1775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001776 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001777 return false;
1778 }
1779
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001780 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001781 {
1782 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1783 // not generate an error.
1784 return false;
1785 }
1786
1787 if (!ValidDebugSeverity(severity))
1788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001789 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001790 return false;
1791 }
1792
1793 if (!ValidDebugType(type))
1794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001795 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001796 return false;
1797 }
1798
1799 if (!ValidDebugSource(source, true))
1800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001801 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001802 return false;
1803 }
1804
1805 size_t messageLength = (length < 0) ? strlen(buf) : length;
1806 if (messageLength > context->getExtensions().maxDebugMessageLength)
1807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidValue()
1809 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001810 return false;
1811 }
1812
Geoff Lange102fee2015-12-10 11:23:30 -05001813 return true;
1814}
1815
1816bool ValidateDebugMessageCallbackKHR(Context *context,
1817 GLDEBUGPROCKHR callback,
1818 const void *userParam)
1819{
1820 if (!context->getExtensions().debug)
1821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001822 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001823 return false;
1824 }
1825
Geoff Lange102fee2015-12-10 11:23:30 -05001826 return true;
1827}
1828
1829bool ValidateGetDebugMessageLogKHR(Context *context,
1830 GLuint count,
1831 GLsizei bufSize,
1832 GLenum *sources,
1833 GLenum *types,
1834 GLuint *ids,
1835 GLenum *severities,
1836 GLsizei *lengths,
1837 GLchar *messageLog)
1838{
1839 if (!context->getExtensions().debug)
1840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001841 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001842 return false;
1843 }
1844
Geoff Lang70d0f492015-12-10 17:45:46 -05001845 if (bufSize < 0 && messageLog != nullptr)
1846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001847 context->handleError(InvalidValue()
1848 << "bufSize must be positive if messageLog is not null.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001849 return false;
1850 }
1851
Geoff Lange102fee2015-12-10 11:23:30 -05001852 return true;
1853}
1854
1855bool ValidatePushDebugGroupKHR(Context *context,
1856 GLenum source,
1857 GLuint id,
1858 GLsizei length,
1859 const GLchar *message)
1860{
1861 if (!context->getExtensions().debug)
1862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001863 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001864 return false;
1865 }
1866
Geoff Lang70d0f492015-12-10 17:45:46 -05001867 if (!ValidDebugSource(source, true))
1868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001869 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001870 return false;
1871 }
1872
1873 size_t messageLength = (length < 0) ? strlen(message) : length;
1874 if (messageLength > context->getExtensions().maxDebugMessageLength)
1875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001876 context->handleError(InvalidValue()
1877 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001878 return false;
1879 }
1880
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001881 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001882 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001884 context
1885 ->handleError(StackOverflow()
1886 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001887 return false;
1888 }
1889
Geoff Lange102fee2015-12-10 11:23:30 -05001890 return true;
1891}
1892
1893bool ValidatePopDebugGroupKHR(Context *context)
1894{
1895 if (!context->getExtensions().debug)
1896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001897 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001898 return false;
1899 }
1900
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001901 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001902 if (currentStackSize <= 1)
1903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001904 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001905 return false;
1906 }
1907
1908 return true;
1909}
1910
1911static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1912{
1913 switch (identifier)
1914 {
1915 case GL_BUFFER:
1916 if (context->getBuffer(name) == nullptr)
1917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001918 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001919 return false;
1920 }
1921 return true;
1922
1923 case GL_SHADER:
1924 if (context->getShader(name) == nullptr)
1925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001926 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001927 return false;
1928 }
1929 return true;
1930
1931 case GL_PROGRAM:
1932 if (context->getProgram(name) == nullptr)
1933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001934 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001935 return false;
1936 }
1937 return true;
1938
1939 case GL_VERTEX_ARRAY:
1940 if (context->getVertexArray(name) == nullptr)
1941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001942 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001943 return false;
1944 }
1945 return true;
1946
1947 case GL_QUERY:
1948 if (context->getQuery(name) == nullptr)
1949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001950 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001951 return false;
1952 }
1953 return true;
1954
1955 case GL_TRANSFORM_FEEDBACK:
1956 if (context->getTransformFeedback(name) == nullptr)
1957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001958 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001959 return false;
1960 }
1961 return true;
1962
1963 case GL_SAMPLER:
1964 if (context->getSampler(name) == nullptr)
1965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001966 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001967 return false;
1968 }
1969 return true;
1970
1971 case GL_TEXTURE:
1972 if (context->getTexture(name) == nullptr)
1973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001974 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001975 return false;
1976 }
1977 return true;
1978
1979 case GL_RENDERBUFFER:
1980 if (context->getRenderbuffer(name) == nullptr)
1981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001982 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001983 return false;
1984 }
1985 return true;
1986
1987 case GL_FRAMEBUFFER:
1988 if (context->getFramebuffer(name) == nullptr)
1989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001990 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001991 return false;
1992 }
1993 return true;
1994
1995 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001996 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001997 return false;
1998 }
Geoff Lange102fee2015-12-10 11:23:30 -05001999}
2000
Martin Radev9d901792016-07-15 15:58:58 +03002001static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2002{
2003 size_t labelLength = 0;
2004
2005 if (length < 0)
2006 {
2007 if (label != nullptr)
2008 {
2009 labelLength = strlen(label);
2010 }
2011 }
2012 else
2013 {
2014 labelLength = static_cast<size_t>(length);
2015 }
2016
2017 if (labelLength > context->getExtensions().maxLabelLength)
2018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002019 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002020 return false;
2021 }
2022
2023 return true;
2024}
2025
Geoff Lange102fee2015-12-10 11:23:30 -05002026bool ValidateObjectLabelKHR(Context *context,
2027 GLenum identifier,
2028 GLuint name,
2029 GLsizei length,
2030 const GLchar *label)
2031{
2032 if (!context->getExtensions().debug)
2033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002034 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002035 return false;
2036 }
2037
Geoff Lang70d0f492015-12-10 17:45:46 -05002038 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2039 {
2040 return false;
2041 }
2042
Martin Radev9d901792016-07-15 15:58:58 +03002043 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002044 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002045 return false;
2046 }
2047
Geoff Lange102fee2015-12-10 11:23:30 -05002048 return true;
2049}
2050
2051bool ValidateGetObjectLabelKHR(Context *context,
2052 GLenum identifier,
2053 GLuint name,
2054 GLsizei bufSize,
2055 GLsizei *length,
2056 GLchar *label)
2057{
2058 if (!context->getExtensions().debug)
2059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002060 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002061 return false;
2062 }
2063
Geoff Lang70d0f492015-12-10 17:45:46 -05002064 if (bufSize < 0)
2065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002066 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002067 return false;
2068 }
2069
2070 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2071 {
2072 return false;
2073 }
2074
Martin Radev9d901792016-07-15 15:58:58 +03002075 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002076}
2077
2078static bool ValidateObjectPtrName(Context *context, const void *ptr)
2079{
2080 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002082 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002083 return false;
2084 }
2085
Geoff Lange102fee2015-12-10 11:23:30 -05002086 return true;
2087}
2088
2089bool ValidateObjectPtrLabelKHR(Context *context,
2090 const void *ptr,
2091 GLsizei length,
2092 const GLchar *label)
2093{
2094 if (!context->getExtensions().debug)
2095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002096 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002097 return false;
2098 }
2099
Geoff Lang70d0f492015-12-10 17:45:46 -05002100 if (!ValidateObjectPtrName(context, ptr))
2101 {
2102 return false;
2103 }
2104
Martin Radev9d901792016-07-15 15:58:58 +03002105 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002106 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002107 return false;
2108 }
2109
Geoff Lange102fee2015-12-10 11:23:30 -05002110 return true;
2111}
2112
2113bool ValidateGetObjectPtrLabelKHR(Context *context,
2114 const void *ptr,
2115 GLsizei bufSize,
2116 GLsizei *length,
2117 GLchar *label)
2118{
2119 if (!context->getExtensions().debug)
2120 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002121 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002122 return false;
2123 }
2124
Geoff Lang70d0f492015-12-10 17:45:46 -05002125 if (bufSize < 0)
2126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002127 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002128 return false;
2129 }
2130
2131 if (!ValidateObjectPtrName(context, ptr))
2132 {
2133 return false;
2134 }
2135
Martin Radev9d901792016-07-15 15:58:58 +03002136 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002137}
2138
2139bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2140{
2141 if (!context->getExtensions().debug)
2142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002143 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002144 return false;
2145 }
2146
Geoff Lang70d0f492015-12-10 17:45:46 -05002147 // TODO: represent this in Context::getQueryParameterInfo.
2148 switch (pname)
2149 {
2150 case GL_DEBUG_CALLBACK_FUNCTION:
2151 case GL_DEBUG_CALLBACK_USER_PARAM:
2152 break;
2153
2154 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002155 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002156 return false;
2157 }
2158
Geoff Lange102fee2015-12-10 11:23:30 -05002159 return true;
2160}
Jamie Madillc29968b2016-01-20 11:17:23 -05002161
2162bool ValidateBlitFramebufferANGLE(Context *context,
2163 GLint srcX0,
2164 GLint srcY0,
2165 GLint srcX1,
2166 GLint srcY1,
2167 GLint dstX0,
2168 GLint dstY0,
2169 GLint dstX1,
2170 GLint dstY1,
2171 GLbitfield mask,
2172 GLenum filter)
2173{
2174 if (!context->getExtensions().framebufferBlit)
2175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002176 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002177 return false;
2178 }
2179
2180 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2181 {
2182 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002183 context->handleError(InvalidOperation() << "Scaling and flipping in "
2184 "BlitFramebufferANGLE not supported by this "
2185 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002186 return false;
2187 }
2188
2189 if (filter == GL_LINEAR)
2190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002191 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002192 return false;
2193 }
2194
Jamie Madill51f40ec2016-06-15 14:06:00 -04002195 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2196 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002197
2198 if (mask & GL_COLOR_BUFFER_BIT)
2199 {
2200 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2201 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2202
2203 if (readColorAttachment && drawColorAttachment)
2204 {
2205 if (!(readColorAttachment->type() == GL_TEXTURE &&
2206 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2207 readColorAttachment->type() != GL_RENDERBUFFER &&
2208 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002210 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002211 return false;
2212 }
2213
Geoff Langa15472a2015-08-11 11:48:03 -04002214 for (size_t drawbufferIdx = 0;
2215 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002216 {
Geoff Langa15472a2015-08-11 11:48:03 -04002217 const FramebufferAttachment *attachment =
2218 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2219 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002220 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002221 if (!(attachment->type() == GL_TEXTURE &&
2222 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2223 attachment->type() != GL_RENDERBUFFER &&
2224 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002226 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002227 return false;
2228 }
2229
2230 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002231 if (!Format::SameSized(attachment->getFormat(),
2232 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002234 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002235 return false;
2236 }
2237 }
2238 }
2239
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002240 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002241 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2242 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002244 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002245 return false;
2246 }
2247 }
2248 }
2249
2250 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2251 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2252 for (size_t i = 0; i < 2; i++)
2253 {
2254 if (mask & masks[i])
2255 {
2256 const FramebufferAttachment *readBuffer =
2257 readFramebuffer->getAttachment(attachments[i]);
2258 const FramebufferAttachment *drawBuffer =
2259 drawFramebuffer->getAttachment(attachments[i]);
2260
2261 if (readBuffer && drawBuffer)
2262 {
2263 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2264 dstX0, dstY0, dstX1, dstY1))
2265 {
2266 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002267 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2268 "stencil blits are supported by "
2269 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002270 return false;
2271 }
2272
2273 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002275 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002276 return false;
2277 }
2278 }
2279 }
2280 }
2281
2282 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2283 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002284}
Jamie Madillc29968b2016-01-20 11:17:23 -05002285
2286bool ValidateClear(ValidationContext *context, GLbitfield mask)
2287{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002288 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002289 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002291 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002292 return false;
2293 }
2294
2295 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05002298 return false;
2299 }
2300
Geoff Lang76e65652017-03-27 14:58:02 -04002301 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2302 {
2303 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2304 GL_SIGNED_NORMALIZED};
2305
2306 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2307 drawBufferIdx++)
2308 {
2309 if (!ValidateWebGLFramebufferAttachmentClearType(
2310 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2311 {
2312 return false;
2313 }
2314 }
2315 }
2316
Jamie Madillc29968b2016-01-20 11:17:23 -05002317 return true;
2318}
2319
2320bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2321{
2322 if (!context->getExtensions().drawBuffers)
2323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002324 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002325 return false;
2326 }
2327
2328 return ValidateDrawBuffersBase(context, n, bufs);
2329}
2330
Jamie Madill73a84962016-02-12 09:27:23 -05002331bool ValidateTexImage2D(Context *context,
2332 GLenum target,
2333 GLint level,
2334 GLint internalformat,
2335 GLsizei width,
2336 GLsizei height,
2337 GLint border,
2338 GLenum format,
2339 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002340 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002341{
Martin Radev1be913c2016-07-11 17:59:16 +03002342 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002343 {
2344 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002345 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002346 }
2347
Martin Radev1be913c2016-07-11 17:59:16 +03002348 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002349 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002350 0, 0, width, height, 1, border, format, type, -1,
2351 pixels);
2352}
2353
2354bool ValidateTexImage2DRobust(Context *context,
2355 GLenum target,
2356 GLint level,
2357 GLint internalformat,
2358 GLsizei width,
2359 GLsizei height,
2360 GLint border,
2361 GLenum format,
2362 GLenum type,
2363 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002364 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002365{
2366 if (!ValidateRobustEntryPoint(context, bufSize))
2367 {
2368 return false;
2369 }
2370
2371 if (context->getClientMajorVersion() < 3)
2372 {
2373 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2374 0, 0, width, height, border, format, type, bufSize,
2375 pixels);
2376 }
2377
2378 ASSERT(context->getClientMajorVersion() >= 3);
2379 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2380 0, 0, width, height, 1, border, format, type, bufSize,
2381 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002382}
2383
2384bool ValidateTexSubImage2D(Context *context,
2385 GLenum target,
2386 GLint level,
2387 GLint xoffset,
2388 GLint yoffset,
2389 GLsizei width,
2390 GLsizei height,
2391 GLenum format,
2392 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002393 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002394{
2395
Martin Radev1be913c2016-07-11 17:59:16 +03002396 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002397 {
2398 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002399 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002400 }
2401
Martin Radev1be913c2016-07-11 17:59:16 +03002402 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002403 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002404 yoffset, 0, width, height, 1, 0, format, type, -1,
2405 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002406}
2407
Geoff Langc52f6f12016-10-14 10:18:00 -04002408bool ValidateTexSubImage2DRobustANGLE(Context *context,
2409 GLenum target,
2410 GLint level,
2411 GLint xoffset,
2412 GLint yoffset,
2413 GLsizei width,
2414 GLsizei height,
2415 GLenum format,
2416 GLenum type,
2417 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002418 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002419{
2420 if (!ValidateRobustEntryPoint(context, bufSize))
2421 {
2422 return false;
2423 }
2424
2425 if (context->getClientMajorVersion() < 3)
2426 {
2427 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2428 yoffset, width, height, 0, format, type, bufSize,
2429 pixels);
2430 }
2431
2432 ASSERT(context->getClientMajorVersion() >= 3);
2433 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2434 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2435 pixels);
2436}
2437
Jamie Madill73a84962016-02-12 09:27:23 -05002438bool ValidateCompressedTexImage2D(Context *context,
2439 GLenum target,
2440 GLint level,
2441 GLenum internalformat,
2442 GLsizei width,
2443 GLsizei height,
2444 GLint border,
2445 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002446 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002447{
Martin Radev1be913c2016-07-11 17:59:16 +03002448 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002449 {
2450 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002451 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002452 {
2453 return false;
2454 }
2455 }
2456 else
2457 {
Martin Radev1be913c2016-07-11 17:59:16 +03002458 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002459 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002460 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002461 data))
2462 {
2463 return false;
2464 }
2465 }
2466
Geoff Langca271392017-04-05 12:30:00 -04002467 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002468 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002469 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002470 if (blockSizeOrErr.isError())
2471 {
2472 context->handleError(blockSizeOrErr.getError());
2473 return false;
2474 }
2475
2476 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002478 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002479 return false;
2480 }
2481
2482 return true;
2483}
2484
Corentin Wallezb2931602017-04-11 15:58:57 -04002485bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2486 GLenum target,
2487 GLint level,
2488 GLenum internalformat,
2489 GLsizei width,
2490 GLsizei height,
2491 GLint border,
2492 GLsizei imageSize,
2493 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002494 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002495{
2496 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2497 {
2498 return false;
2499 }
2500
2501 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2502 border, imageSize, data);
2503}
2504bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2505 GLenum target,
2506 GLint level,
2507 GLint xoffset,
2508 GLint yoffset,
2509 GLsizei width,
2510 GLsizei height,
2511 GLenum format,
2512 GLsizei imageSize,
2513 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002514 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002515{
2516 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2517 {
2518 return false;
2519 }
2520
2521 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2522 format, imageSize, data);
2523}
2524
Jamie Madill73a84962016-02-12 09:27:23 -05002525bool ValidateCompressedTexSubImage2D(Context *context,
2526 GLenum target,
2527 GLint level,
2528 GLint xoffset,
2529 GLint yoffset,
2530 GLsizei width,
2531 GLsizei height,
2532 GLenum format,
2533 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002534 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002535{
Martin Radev1be913c2016-07-11 17:59:16 +03002536 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002537 {
2538 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002539 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002540 {
2541 return false;
2542 }
2543 }
2544 else
2545 {
Martin Radev1be913c2016-07-11 17:59:16 +03002546 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002547 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002548 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002549 data))
2550 {
2551 return false;
2552 }
2553 }
2554
Geoff Langca271392017-04-05 12:30:00 -04002555 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002556 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002557 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002558 if (blockSizeOrErr.isError())
2559 {
2560 context->handleError(blockSizeOrErr.getError());
2561 return false;
2562 }
2563
2564 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002566 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002567 return false;
2568 }
2569
2570 return true;
2571}
2572
Olli Etuaho4f667482016-03-30 15:56:35 +03002573bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2574{
Geoff Lang496c02d2016-10-20 11:38:11 -07002575 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002576}
2577
2578bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2579{
2580 if (!context->getExtensions().mapBuffer)
2581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002582 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002583 return false;
2584 }
2585
2586 if (!ValidBufferTarget(context, target))
2587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002588 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002589 return false;
2590 }
2591
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002592 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002593
2594 if (buffer == nullptr)
2595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002596 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002597 return false;
2598 }
2599
2600 if (access != GL_WRITE_ONLY_OES)
2601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002602 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002603 return false;
2604 }
2605
2606 if (buffer->isMapped())
2607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002608 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002609 return false;
2610 }
2611
2612 return true;
2613}
2614
2615bool ValidateUnmapBufferOES(Context *context, GLenum target)
2616{
2617 if (!context->getExtensions().mapBuffer)
2618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002619 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002620 return false;
2621 }
2622
2623 return ValidateUnmapBufferBase(context, target);
2624}
2625
2626bool ValidateMapBufferRangeEXT(Context *context,
2627 GLenum target,
2628 GLintptr offset,
2629 GLsizeiptr length,
2630 GLbitfield access)
2631{
2632 if (!context->getExtensions().mapBufferRange)
2633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002634 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002635 return false;
2636 }
2637
2638 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2639}
2640
2641bool ValidateFlushMappedBufferRangeEXT(Context *context,
2642 GLenum target,
2643 GLintptr offset,
2644 GLsizeiptr length)
2645{
2646 if (!context->getExtensions().mapBufferRange)
2647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002648 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002649 return false;
2650 }
2651
2652 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2653}
2654
Ian Ewell54f87462016-03-10 13:47:21 -05002655bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2656{
2657 Texture *textureObject = context->getTexture(texture);
2658 if (textureObject && textureObject->getTarget() != target && texture != 0)
2659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002660 context->handleError(InvalidOperation() << "Invalid texture");
Ian Ewell54f87462016-03-10 13:47:21 -05002661 return false;
2662 }
2663
Geoff Langf41a7152016-09-19 15:11:17 -04002664 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2665 !context->isTextureGenerated(texture))
2666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002667 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002668 return false;
2669 }
2670
Ian Ewell54f87462016-03-10 13:47:21 -05002671 switch (target)
2672 {
2673 case GL_TEXTURE_2D:
2674 case GL_TEXTURE_CUBE_MAP:
2675 break;
2676
2677 case GL_TEXTURE_3D:
2678 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002679 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002681 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002682 return false;
2683 }
2684 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002685
2686 case GL_TEXTURE_2D_MULTISAMPLE:
2687 if (context->getClientVersion() < Version(3, 1))
2688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002689 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002690 return false;
2691 }
Geoff Lang3b573612016-10-31 14:08:10 -04002692 break;
2693
Ian Ewell54f87462016-03-10 13:47:21 -05002694 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002695 if (!context->getExtensions().eglImageExternal &&
2696 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002698 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002699 return false;
2700 }
2701 break;
2702 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002703 context->handleError(InvalidEnum() << "Invalid target");
Ian Ewell54f87462016-03-10 13:47:21 -05002704 return false;
2705 }
2706
2707 return true;
2708}
2709
Geoff Langd8605522016-04-13 10:19:12 -04002710bool ValidateBindUniformLocationCHROMIUM(Context *context,
2711 GLuint program,
2712 GLint location,
2713 const GLchar *name)
2714{
2715 if (!context->getExtensions().bindUniformLocation)
2716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002717 context->handleError(InvalidOperation()
2718 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002719 return false;
2720 }
2721
2722 Program *programObject = GetValidProgram(context, program);
2723 if (!programObject)
2724 {
2725 return false;
2726 }
2727
2728 if (location < 0)
2729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002730 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002731 return false;
2732 }
2733
2734 const Caps &caps = context->getCaps();
2735 if (static_cast<size_t>(location) >=
2736 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002738 context->handleError(InvalidValue() << "Location must be less than "
2739 "(MAX_VERTEX_UNIFORM_VECTORS + "
2740 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002741 return false;
2742 }
2743
Geoff Langfc32e8b2017-05-31 14:16:59 -04002744 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2745 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04002746 if (context->getExtensions().webglCompatibility &&
2747 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002749 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04002750 return false;
2751 }
2752
Geoff Langd8605522016-04-13 10:19:12 -04002753 if (strncmp(name, "gl_", 3) == 0)
2754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002755 context->handleError(InvalidOperation()
2756 << "Name cannot start with the reserved \"gl_\" prefix.");
Geoff Langd8605522016-04-13 10:19:12 -04002757 return false;
2758 }
2759
2760 return true;
2761}
2762
Jamie Madille2e406c2016-06-02 13:04:10 -04002763bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002764{
2765 if (!context->getExtensions().framebufferMixedSamples)
2766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002767 context->handleError(InvalidOperation()
2768 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002769 return false;
2770 }
2771 switch (components)
2772 {
2773 case GL_RGB:
2774 case GL_RGBA:
2775 case GL_ALPHA:
2776 case GL_NONE:
2777 break;
2778 default:
2779 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002780 InvalidEnum()
2781 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002782 return false;
2783 }
2784
2785 return true;
2786}
2787
Sami Väisänene45e53b2016-05-25 10:36:04 +03002788// CHROMIUM_path_rendering
2789
2790bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2791{
2792 if (!context->getExtensions().pathRendering)
2793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002794 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002795 return false;
2796 }
2797 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002799 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002800 return false;
2801 }
2802 if (matrix == nullptr)
2803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002804 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002805 return false;
2806 }
2807 return true;
2808}
2809
2810bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2811{
2812 if (!context->getExtensions().pathRendering)
2813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002814 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002815 return false;
2816 }
2817 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002819 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002820 return false;
2821 }
2822 return true;
2823}
2824
2825bool ValidateGenPaths(Context *context, GLsizei range)
2826{
2827 if (!context->getExtensions().pathRendering)
2828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002829 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002830 return false;
2831 }
2832
2833 // range = 0 is undefined in NV_path_rendering.
2834 // we add stricter semantic check here and require a non zero positive range.
2835 if (range <= 0)
2836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002837 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002838 return false;
2839 }
2840
2841 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002843 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002844 return false;
2845 }
2846
2847 return true;
2848}
2849
2850bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2851{
2852 if (!context->getExtensions().pathRendering)
2853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002854 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002855 return false;
2856 }
2857
2858 // range = 0 is undefined in NV_path_rendering.
2859 // we add stricter semantic check here and require a non zero positive range.
2860 if (range <= 0)
2861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002862 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002863 return false;
2864 }
2865
2866 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2867 checkedRange += range;
2868
2869 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002871 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002872 return false;
2873 }
2874 return true;
2875}
2876
2877bool ValidatePathCommands(Context *context,
2878 GLuint path,
2879 GLsizei numCommands,
2880 const GLubyte *commands,
2881 GLsizei numCoords,
2882 GLenum coordType,
2883 const void *coords)
2884{
2885 if (!context->getExtensions().pathRendering)
2886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002887 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002888 return false;
2889 }
2890 if (!context->hasPath(path))
2891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002892 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002893 return false;
2894 }
2895
2896 if (numCommands < 0)
2897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002898 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002899 return false;
2900 }
2901 else if (numCommands > 0)
2902 {
2903 if (!commands)
2904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002905 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002906 return false;
2907 }
2908 }
2909
2910 if (numCoords < 0)
2911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002912 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002913 return false;
2914 }
2915 else if (numCoords > 0)
2916 {
2917 if (!coords)
2918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002919 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002920 return false;
2921 }
2922 }
2923
2924 std::uint32_t coordTypeSize = 0;
2925 switch (coordType)
2926 {
2927 case GL_BYTE:
2928 coordTypeSize = sizeof(GLbyte);
2929 break;
2930
2931 case GL_UNSIGNED_BYTE:
2932 coordTypeSize = sizeof(GLubyte);
2933 break;
2934
2935 case GL_SHORT:
2936 coordTypeSize = sizeof(GLshort);
2937 break;
2938
2939 case GL_UNSIGNED_SHORT:
2940 coordTypeSize = sizeof(GLushort);
2941 break;
2942
2943 case GL_FLOAT:
2944 coordTypeSize = sizeof(GLfloat);
2945 break;
2946
2947 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002948 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002949 return false;
2950 }
2951
2952 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2953 checkedSize += (coordTypeSize * numCoords);
2954 if (!checkedSize.IsValid())
2955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002956 context->handleError(InvalidOperation() << "Coord size overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002957 return false;
2958 }
2959
2960 // early return skips command data validation when it doesn't exist.
2961 if (!commands)
2962 return true;
2963
2964 GLsizei expectedNumCoords = 0;
2965 for (GLsizei i = 0; i < numCommands; ++i)
2966 {
2967 switch (commands[i])
2968 {
2969 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2970 break;
2971 case GL_MOVE_TO_CHROMIUM:
2972 case GL_LINE_TO_CHROMIUM:
2973 expectedNumCoords += 2;
2974 break;
2975 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2976 expectedNumCoords += 4;
2977 break;
2978 case GL_CUBIC_CURVE_TO_CHROMIUM:
2979 expectedNumCoords += 6;
2980 break;
2981 case GL_CONIC_CURVE_TO_CHROMIUM:
2982 expectedNumCoords += 5;
2983 break;
2984 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002985 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002986 return false;
2987 }
2988 }
2989 if (expectedNumCoords != numCoords)
2990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002991 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002992 return false;
2993 }
2994
2995 return true;
2996}
2997
2998bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2999{
3000 if (!context->getExtensions().pathRendering)
3001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003002 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003003 return false;
3004 }
3005 if (!context->hasPath(path))
3006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003007 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003008 return false;
3009 }
3010
3011 switch (pname)
3012 {
3013 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3014 if (value < 0.0f)
3015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003016 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003017 return false;
3018 }
3019 break;
3020 case GL_PATH_END_CAPS_CHROMIUM:
3021 switch (static_cast<GLenum>(value))
3022 {
3023 case GL_FLAT_CHROMIUM:
3024 case GL_SQUARE_CHROMIUM:
3025 case GL_ROUND_CHROMIUM:
3026 break;
3027 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003028 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003029 return false;
3030 }
3031 break;
3032 case GL_PATH_JOIN_STYLE_CHROMIUM:
3033 switch (static_cast<GLenum>(value))
3034 {
3035 case GL_MITER_REVERT_CHROMIUM:
3036 case GL_BEVEL_CHROMIUM:
3037 case GL_ROUND_CHROMIUM:
3038 break;
3039 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003040 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003041 return false;
3042 }
3043 case GL_PATH_MITER_LIMIT_CHROMIUM:
3044 if (value < 0.0f)
3045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003046 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003047 return false;
3048 }
3049 break;
3050
3051 case GL_PATH_STROKE_BOUND_CHROMIUM:
3052 // no errors, only clamping.
3053 break;
3054
3055 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003056 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003057 return false;
3058 }
3059 return true;
3060}
3061
3062bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3063{
3064 if (!context->getExtensions().pathRendering)
3065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003066 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003067 return false;
3068 }
3069
3070 if (!context->hasPath(path))
3071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003072 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003073 return false;
3074 }
3075 if (!value)
3076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003077 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003078 return false;
3079 }
3080
3081 switch (pname)
3082 {
3083 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3084 case GL_PATH_END_CAPS_CHROMIUM:
3085 case GL_PATH_JOIN_STYLE_CHROMIUM:
3086 case GL_PATH_MITER_LIMIT_CHROMIUM:
3087 case GL_PATH_STROKE_BOUND_CHROMIUM:
3088 break;
3089
3090 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003091 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003092 return false;
3093 }
3094
3095 return true;
3096}
3097
3098bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3099{
3100 if (!context->getExtensions().pathRendering)
3101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003102 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003103 return false;
3104 }
3105
3106 switch (func)
3107 {
3108 case GL_NEVER:
3109 case GL_ALWAYS:
3110 case GL_LESS:
3111 case GL_LEQUAL:
3112 case GL_EQUAL:
3113 case GL_GEQUAL:
3114 case GL_GREATER:
3115 case GL_NOTEQUAL:
3116 break;
3117 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003118 context->handleError(InvalidEnum() << "Invalid stencil function.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003119 return false;
3120 }
3121
3122 return true;
3123}
3124
3125// Note that the spec specifies that for the path drawing commands
3126// if the path object is not an existing path object the command
3127// does nothing and no error is generated.
3128// However if the path object exists but has not been specified any
3129// commands then an error is generated.
3130
3131bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3132{
3133 if (!context->getExtensions().pathRendering)
3134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003135 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003136 return false;
3137 }
3138 if (context->hasPath(path) && !context->hasPathData(path))
3139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003140 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003141 return false;
3142 }
3143
3144 switch (fillMode)
3145 {
3146 case GL_COUNT_UP_CHROMIUM:
3147 case GL_COUNT_DOWN_CHROMIUM:
3148 break;
3149 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003150 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003151 return false;
3152 }
3153
3154 if (!isPow2(mask + 1))
3155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003156 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003157 return false;
3158 }
3159
3160 return true;
3161}
3162
3163bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3164{
3165 if (!context->getExtensions().pathRendering)
3166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003167 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003168 return false;
3169 }
3170 if (context->hasPath(path) && !context->hasPathData(path))
3171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003172 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003173 return false;
3174 }
3175
3176 return true;
3177}
3178
3179bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3180{
3181 if (!context->getExtensions().pathRendering)
3182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003183 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003184 return false;
3185 }
3186 if (context->hasPath(path) && !context->hasPathData(path))
3187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003188 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003189 return false;
3190 }
3191
3192 switch (coverMode)
3193 {
3194 case GL_CONVEX_HULL_CHROMIUM:
3195 case GL_BOUNDING_BOX_CHROMIUM:
3196 break;
3197 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003198 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003199 return false;
3200 }
3201 return true;
3202}
3203
3204bool ValidateStencilThenCoverFillPath(Context *context,
3205 GLuint path,
3206 GLenum fillMode,
3207 GLuint mask,
3208 GLenum coverMode)
3209{
3210 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3211 ValidateCoverPath(context, path, coverMode);
3212}
3213
3214bool ValidateStencilThenCoverStrokePath(Context *context,
3215 GLuint path,
3216 GLint reference,
3217 GLuint mask,
3218 GLenum coverMode)
3219{
3220 return ValidateStencilStrokePath(context, path, reference, mask) &&
3221 ValidateCoverPath(context, path, coverMode);
3222}
3223
3224bool ValidateIsPath(Context *context)
3225{
3226 if (!context->getExtensions().pathRendering)
3227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003228 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003229 return false;
3230 }
3231 return true;
3232}
3233
Sami Väisänend59ca052016-06-21 16:10:00 +03003234bool ValidateCoverFillPathInstanced(Context *context,
3235 GLsizei numPaths,
3236 GLenum pathNameType,
3237 const void *paths,
3238 GLuint pathBase,
3239 GLenum coverMode,
3240 GLenum transformType,
3241 const GLfloat *transformValues)
3242{
3243 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3244 transformType, transformValues))
3245 return false;
3246
3247 switch (coverMode)
3248 {
3249 case GL_CONVEX_HULL_CHROMIUM:
3250 case GL_BOUNDING_BOX_CHROMIUM:
3251 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3252 break;
3253 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003254 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003255 return false;
3256 }
3257
3258 return true;
3259}
3260
3261bool ValidateCoverStrokePathInstanced(Context *context,
3262 GLsizei numPaths,
3263 GLenum pathNameType,
3264 const void *paths,
3265 GLuint pathBase,
3266 GLenum coverMode,
3267 GLenum transformType,
3268 const GLfloat *transformValues)
3269{
3270 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3271 transformType, transformValues))
3272 return false;
3273
3274 switch (coverMode)
3275 {
3276 case GL_CONVEX_HULL_CHROMIUM:
3277 case GL_BOUNDING_BOX_CHROMIUM:
3278 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3279 break;
3280 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003281 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003282 return false;
3283 }
3284
3285 return true;
3286}
3287
3288bool ValidateStencilFillPathInstanced(Context *context,
3289 GLsizei numPaths,
3290 GLenum pathNameType,
3291 const void *paths,
3292 GLuint pathBase,
3293 GLenum fillMode,
3294 GLuint mask,
3295 GLenum transformType,
3296 const GLfloat *transformValues)
3297{
3298
3299 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3300 transformType, transformValues))
3301 return false;
3302
3303 switch (fillMode)
3304 {
3305 case GL_COUNT_UP_CHROMIUM:
3306 case GL_COUNT_DOWN_CHROMIUM:
3307 break;
3308 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003309 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003310 return false;
3311 }
3312 if (!isPow2(mask + 1))
3313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003314 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003315 return false;
3316 }
3317 return true;
3318}
3319
3320bool ValidateStencilStrokePathInstanced(Context *context,
3321 GLsizei numPaths,
3322 GLenum pathNameType,
3323 const void *paths,
3324 GLuint pathBase,
3325 GLint reference,
3326 GLuint mask,
3327 GLenum transformType,
3328 const GLfloat *transformValues)
3329{
3330 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3331 transformType, transformValues))
3332 return false;
3333
3334 // no more validation here.
3335
3336 return true;
3337}
3338
3339bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3340 GLsizei numPaths,
3341 GLenum pathNameType,
3342 const void *paths,
3343 GLuint pathBase,
3344 GLenum fillMode,
3345 GLuint mask,
3346 GLenum coverMode,
3347 GLenum transformType,
3348 const GLfloat *transformValues)
3349{
3350 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3351 transformType, transformValues))
3352 return false;
3353
3354 switch (coverMode)
3355 {
3356 case GL_CONVEX_HULL_CHROMIUM:
3357 case GL_BOUNDING_BOX_CHROMIUM:
3358 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3359 break;
3360 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003361 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003362 return false;
3363 }
3364
3365 switch (fillMode)
3366 {
3367 case GL_COUNT_UP_CHROMIUM:
3368 case GL_COUNT_DOWN_CHROMIUM:
3369 break;
3370 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003372 return false;
3373 }
3374 if (!isPow2(mask + 1))
3375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003376 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003377 return false;
3378 }
3379
3380 return true;
3381}
3382
3383bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3384 GLsizei numPaths,
3385 GLenum pathNameType,
3386 const void *paths,
3387 GLuint pathBase,
3388 GLint reference,
3389 GLuint mask,
3390 GLenum coverMode,
3391 GLenum transformType,
3392 const GLfloat *transformValues)
3393{
3394 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3395 transformType, transformValues))
3396 return false;
3397
3398 switch (coverMode)
3399 {
3400 case GL_CONVEX_HULL_CHROMIUM:
3401 case GL_BOUNDING_BOX_CHROMIUM:
3402 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3403 break;
3404 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003405 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003406 return false;
3407 }
3408
3409 return true;
3410}
3411
Sami Väisänen46eaa942016-06-29 10:26:37 +03003412bool ValidateBindFragmentInputLocation(Context *context,
3413 GLuint program,
3414 GLint location,
3415 const GLchar *name)
3416{
3417 if (!context->getExtensions().pathRendering)
3418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003419 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003420 return false;
3421 }
3422
3423 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3424 if (location >= MaxLocation)
3425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003426 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003427 return false;
3428 }
3429
3430 const auto *programObject = context->getProgram(program);
3431 if (!programObject)
3432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003433 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003434 return false;
3435 }
3436
3437 if (!name)
3438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003439 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003440 return false;
3441 }
3442
3443 if (angle::BeginsWith(name, "gl_"))
3444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003445 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003446 return false;
3447 }
3448
3449 return true;
3450}
3451
3452bool ValidateProgramPathFragmentInputGen(Context *context,
3453 GLuint program,
3454 GLint location,
3455 GLenum genMode,
3456 GLint components,
3457 const GLfloat *coeffs)
3458{
3459 if (!context->getExtensions().pathRendering)
3460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003461 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003462 return false;
3463 }
3464
3465 const auto *programObject = context->getProgram(program);
3466 if (!programObject || programObject->isFlaggedForDeletion())
3467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003468 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003469 return false;
3470 }
3471
3472 if (!programObject->isLinked())
3473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003474 context->handleError(InvalidOperation() << "Program is not linked.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003475 return false;
3476 }
3477
3478 switch (genMode)
3479 {
3480 case GL_NONE:
3481 if (components != 0)
3482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003483 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003484 return false;
3485 }
3486 break;
3487
3488 case GL_OBJECT_LINEAR_CHROMIUM:
3489 case GL_EYE_LINEAR_CHROMIUM:
3490 case GL_CONSTANT_CHROMIUM:
3491 if (components < 1 || components > 4)
3492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003493 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003494 return false;
3495 }
3496 if (!coeffs)
3497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003498 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003499 return false;
3500 }
3501 break;
3502
3503 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003504 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003505 return false;
3506 }
3507
3508 // If the location is -1 then the command is silently ignored
3509 // and no further validation is needed.
3510 if (location == -1)
3511 return true;
3512
Jamie Madillbd044ed2017-06-05 12:59:21 -04003513 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003514
3515 if (!binding.valid)
3516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003517 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003518 return false;
3519 }
3520
3521 if (binding.type != GL_NONE)
3522 {
3523 GLint expectedComponents = 0;
3524 switch (binding.type)
3525 {
3526 case GL_FLOAT:
3527 expectedComponents = 1;
3528 break;
3529 case GL_FLOAT_VEC2:
3530 expectedComponents = 2;
3531 break;
3532 case GL_FLOAT_VEC3:
3533 expectedComponents = 3;
3534 break;
3535 case GL_FLOAT_VEC4:
3536 expectedComponents = 4;
3537 break;
3538 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003539 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003540 InvalidOperation()
3541 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003542 return false;
3543 }
3544 if (expectedComponents != components && genMode != GL_NONE)
3545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003546 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003547 return false;
3548 }
3549 }
3550 return true;
3551}
3552
Geoff Lang97073d12016-04-20 10:42:34 -07003553bool ValidateCopyTextureCHROMIUM(Context *context,
3554 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003555 GLint sourceLevel,
3556 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003557 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003558 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003559 GLint internalFormat,
3560 GLenum destType,
3561 GLboolean unpackFlipY,
3562 GLboolean unpackPremultiplyAlpha,
3563 GLboolean unpackUnmultiplyAlpha)
3564{
3565 if (!context->getExtensions().copyTexture)
3566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003567 context->handleError(InvalidOperation()
3568 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003569 return false;
3570 }
3571
Geoff Lang4f0e0032017-05-01 16:04:35 -04003572 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003573 if (source == nullptr)
3574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003575 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003576 return false;
3577 }
3578
3579 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003582 return false;
3583 }
3584
3585 GLenum sourceTarget = source->getTarget();
3586 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003587
3588 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003590 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003591 return false;
3592 }
3593
Geoff Lang4f0e0032017-05-01 16:04:35 -04003594 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3595 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3596 if (sourceWidth == 0 || sourceHeight == 0)
3597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003598 context->handleError(InvalidValue()
3599 << "The source level of the source texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003600 return false;
3601 }
3602
3603 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3604 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003606 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003607 return false;
3608 }
3609
Geoff Lang4f0e0032017-05-01 16:04:35 -04003610 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003611 if (dest == nullptr)
3612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidValue()
3614 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003615 return false;
3616 }
3617
Geoff Lang4f0e0032017-05-01 16:04:35 -04003618 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003621 return false;
3622 }
3623
Geoff Lang4f0e0032017-05-01 16:04:35 -04003624 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3625 sourceHeight))
3626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003627 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003628 return false;
3629 }
3630
Geoff Lang97073d12016-04-20 10:42:34 -07003631 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(InvalidOperation()
3634 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003635 return false;
3636 }
3637
Geoff Lang4f0e0032017-05-01 16:04:35 -04003638 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(
3641 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003642 return false;
3643 }
3644
Geoff Lang97073d12016-04-20 10:42:34 -07003645 if (dest->getImmutableFormat())
3646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003647 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003648 return false;
3649 }
3650
3651 return true;
3652}
3653
3654bool ValidateCopySubTextureCHROMIUM(Context *context,
3655 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003656 GLint sourceLevel,
3657 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003658 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003659 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003660 GLint xoffset,
3661 GLint yoffset,
3662 GLint x,
3663 GLint y,
3664 GLsizei width,
3665 GLsizei height,
3666 GLboolean unpackFlipY,
3667 GLboolean unpackPremultiplyAlpha,
3668 GLboolean unpackUnmultiplyAlpha)
3669{
3670 if (!context->getExtensions().copyTexture)
3671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003672 context->handleError(InvalidOperation()
3673 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003674 return false;
3675 }
3676
Geoff Lang4f0e0032017-05-01 16:04:35 -04003677 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003678 if (source == nullptr)
3679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003680 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003681 return false;
3682 }
3683
3684 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003686 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003687 return false;
3688 }
3689
3690 GLenum sourceTarget = source->getTarget();
3691 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003692
3693 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003695 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003696 return false;
3697 }
3698
3699 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3700 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003702 context->handleError(InvalidValue()
3703 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003704 return false;
3705 }
3706
3707 if (x < 0 || y < 0)
3708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003710 return false;
3711 }
3712
3713 if (width < 0 || height < 0)
3714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003715 context->handleError(InvalidValue() << "width and height cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003716 return false;
3717 }
3718
Geoff Lang4f0e0032017-05-01 16:04:35 -04003719 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3720 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003722 context->handleError(InvalidValue() << "Source texture not large enough to copy from.");
Geoff Lang97073d12016-04-20 10:42:34 -07003723 return false;
3724 }
3725
Geoff Lang4f0e0032017-05-01 16:04:35 -04003726 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3727 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003730 return false;
3731 }
3732
Geoff Lang4f0e0032017-05-01 16:04:35 -04003733 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003734 if (dest == nullptr)
3735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003736 context->handleError(InvalidValue()
3737 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003738 return false;
3739 }
3740
Geoff Lang4f0e0032017-05-01 16:04:35 -04003741 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003744 return false;
3745 }
3746
Geoff Lang4f0e0032017-05-01 16:04:35 -04003747 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003749 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003750 return false;
3751 }
3752
Geoff Lang4f0e0032017-05-01 16:04:35 -04003753 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3754 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04003755 context
3756 ->handleError(InvalidOperation()
3757 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003758 return false;
3759 }
3760
3761 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3762 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(InvalidOperation()
3765 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003766 return false;
3767 }
3768
3769 if (xoffset < 0 || yoffset < 0)
3770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 context->handleError(InvalidValue() << "xoffset and yoffset cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003772 return false;
3773 }
3774
Geoff Lang4f0e0032017-05-01 16:04:35 -04003775 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3776 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003779 return false;
3780 }
3781
3782 return true;
3783}
3784
Geoff Lang47110bf2016-04-20 11:13:22 -07003785bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3786{
3787 if (!context->getExtensions().copyCompressedTexture)
3788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidOperation()
3790 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003791 return false;
3792 }
3793
3794 const gl::Texture *source = context->getTexture(sourceId);
3795 if (source == nullptr)
3796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003797 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003798 return false;
3799 }
3800
3801 if (source->getTarget() != GL_TEXTURE_2D)
3802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003804 return false;
3805 }
3806
3807 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003809 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003810 return false;
3811 }
3812
3813 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3814 if (!sourceFormat.info->compressed)
3815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003816 context->handleError(InvalidOperation()
3817 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003818 return false;
3819 }
3820
3821 const gl::Texture *dest = context->getTexture(destId);
3822 if (dest == nullptr)
3823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003824 context->handleError(InvalidValue()
3825 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003826 return false;
3827 }
3828
3829 if (dest->getTarget() != GL_TEXTURE_2D)
3830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003831 context->handleError(InvalidValue()
3832 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003833 return false;
3834 }
3835
3836 if (dest->getImmutableFormat())
3837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003838 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003839 return false;
3840 }
3841
3842 return true;
3843}
3844
Martin Radev4c4c8e72016-08-04 12:25:34 +03003845bool ValidateCreateShader(Context *context, GLenum type)
3846{
3847 switch (type)
3848 {
3849 case GL_VERTEX_SHADER:
3850 case GL_FRAGMENT_SHADER:
3851 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003852
Martin Radev4c4c8e72016-08-04 12:25:34 +03003853 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003854 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003856 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003857 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003858 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003859 break;
3860
Martin Radev4c4c8e72016-08-04 12:25:34 +03003861 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003862 context->handleError(InvalidEnum() << "Unknown shader type.");
Martin Radev4c4c8e72016-08-04 12:25:34 +03003863 return false;
3864 }
Jamie Madill29639852016-09-02 15:00:09 -04003865
3866 return true;
3867}
3868
3869bool ValidateBufferData(ValidationContext *context,
3870 GLenum target,
3871 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003872 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003873 GLenum usage)
3874{
3875 if (size < 0)
3876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003877 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003878 return false;
3879 }
3880
3881 switch (usage)
3882 {
3883 case GL_STREAM_DRAW:
3884 case GL_STATIC_DRAW:
3885 case GL_DYNAMIC_DRAW:
3886 break;
3887
3888 case GL_STREAM_READ:
3889 case GL_STREAM_COPY:
3890 case GL_STATIC_READ:
3891 case GL_STATIC_COPY:
3892 case GL_DYNAMIC_READ:
3893 case GL_DYNAMIC_COPY:
3894 if (context->getClientMajorVersion() < 3)
3895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003896 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003897 return false;
3898 }
3899 break;
3900
3901 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003902 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003903 return false;
3904 }
3905
3906 if (!ValidBufferTarget(context, target))
3907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003908 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003909 return false;
3910 }
3911
3912 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3913
3914 if (!buffer)
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003917 return false;
3918 }
3919
3920 return true;
3921}
3922
3923bool ValidateBufferSubData(ValidationContext *context,
3924 GLenum target,
3925 GLintptr offset,
3926 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003927 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003928{
3929 if (size < 0 || offset < 0)
3930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003931 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003932 return false;
3933 }
3934
3935 if (!ValidBufferTarget(context, target))
3936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003937 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003938 return false;
3939 }
3940
3941 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3942
3943 if (!buffer)
3944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003945 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003946 return false;
3947 }
3948
3949 if (buffer->isMapped())
3950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003951 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003952 return false;
3953 }
3954
3955 // Check for possible overflow of size + offset
3956 angle::CheckedNumeric<size_t> checkedSize(size);
3957 checkedSize += offset;
3958 if (!checkedSize.IsValid())
3959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003960 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04003961 return false;
3962 }
3963
3964 if (size + offset > buffer->getSize())
3965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003966 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003967 return false;
3968 }
3969
Martin Radev4c4c8e72016-08-04 12:25:34 +03003970 return true;
3971}
3972
Geoff Langc339c4e2016-11-29 10:37:36 -05003973bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003974{
Geoff Langc339c4e2016-11-29 10:37:36 -05003975 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003977 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04003978 return false;
3979 }
3980
3981 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3982 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003983 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003985 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04003986 return false;
3987 }
3988
3989 return true;
3990}
3991
Jamie Madillef300b12016-10-07 15:12:09 -04003992bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3993{
3994 if (texture < GL_TEXTURE0 ||
3995 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003997 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04003998 return false;
3999 }
4000
4001 return true;
4002}
4003
4004bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4005{
4006 Program *programObject = GetValidProgram(context, program);
4007 if (!programObject)
4008 {
4009 return false;
4010 }
4011
4012 Shader *shaderObject = GetValidShader(context, shader);
4013 if (!shaderObject)
4014 {
4015 return false;
4016 }
4017
4018 switch (shaderObject->getType())
4019 {
4020 case GL_VERTEX_SHADER:
4021 {
4022 if (programObject->getAttachedVertexShader())
4023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004024 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004025 return false;
4026 }
4027 break;
4028 }
4029 case GL_FRAGMENT_SHADER:
4030 {
4031 if (programObject->getAttachedFragmentShader())
4032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004033 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004034 return false;
4035 }
4036 break;
4037 }
4038 case GL_COMPUTE_SHADER:
4039 {
4040 if (programObject->getAttachedComputeShader())
4041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004042 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004043 return false;
4044 }
4045 break;
4046 }
4047 default:
4048 UNREACHABLE();
4049 break;
4050 }
4051
4052 return true;
4053}
4054
Jamie Madill01a80ee2016-11-07 12:06:18 -05004055bool ValidateBindAttribLocation(ValidationContext *context,
4056 GLuint program,
4057 GLuint index,
4058 const GLchar *name)
4059{
4060 if (index >= MAX_VERTEX_ATTRIBS)
4061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidValue() << "Index exceeds MAX_VERTEX_ATTRIBS");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004063 return false;
4064 }
4065
4066 if (strncmp(name, "gl_", 3) == 0)
4067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004068 context->handleError(InvalidOperation() << "Cannot Bind built-in attributes");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004069 return false;
4070 }
4071
Geoff Langfc32e8b2017-05-31 14:16:59 -04004072 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4073 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004074 if (context->getExtensions().webglCompatibility &&
4075 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004077 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004078 return false;
4079 }
4080
Jamie Madill01a80ee2016-11-07 12:06:18 -05004081 return GetValidProgram(context, program) != nullptr;
4082}
4083
4084bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4085{
4086 if (!ValidBufferTarget(context, target))
4087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004088 context->handleError(InvalidEnum() << "Invalid Buffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004089 return false;
4090 }
4091
4092 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4093 !context->isBufferGenerated(buffer))
4094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004095 context->handleError(InvalidOperation() << "Buffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004096 return false;
4097 }
4098
4099 return true;
4100}
4101
4102bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4103{
4104 if (!ValidFramebufferTarget(target))
4105 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004106 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004107 return false;
4108 }
4109
4110 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4111 !context->isFramebufferGenerated(framebuffer))
4112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004113 context->handleError(InvalidOperation() << "Framebuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004114 return false;
4115 }
4116
4117 return true;
4118}
4119
4120bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4121{
4122 if (target != GL_RENDERBUFFER)
4123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004124 context->handleError(InvalidEnum() << "Invalid Renderbuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004125 return false;
4126 }
4127
4128 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4129 !context->isRenderbufferGenerated(renderbuffer))
4130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004131 context->handleError(InvalidOperation() << "Renderbuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004132 return false;
4133 }
4134
4135 return true;
4136}
4137
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004138static bool ValidBlendEquationMode(GLenum mode)
4139{
4140 switch (mode)
4141 {
4142 case GL_FUNC_ADD:
4143 case GL_FUNC_SUBTRACT:
4144 case GL_FUNC_REVERSE_SUBTRACT:
4145 case GL_MIN:
4146 case GL_MAX:
4147 return true;
4148
4149 default:
4150 return false;
4151 }
4152}
4153
Jamie Madillc1d770e2017-04-13 17:31:24 -04004154bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004155 GLfloat red,
4156 GLfloat green,
4157 GLfloat blue,
4158 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004159{
4160 return true;
4161}
4162
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004163bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4164{
4165 if (!ValidBlendEquationMode(mode))
4166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004167 context->handleError(InvalidEnum() << "Invalid blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004168 return false;
4169 }
4170
4171 return true;
4172}
4173
4174bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4175{
4176 if (!ValidBlendEquationMode(modeRGB))
4177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004178 context->handleError(InvalidEnum() << "Invalid RGB blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004179 return false;
4180 }
4181
4182 if (!ValidBlendEquationMode(modeAlpha))
4183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004184 context->handleError(InvalidEnum() << "Invalid alpha blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004185 return false;
4186 }
4187
4188 return true;
4189}
4190
4191bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4192{
4193 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4194}
4195
4196static bool ValidSrcBlendFunc(GLenum srcBlend)
4197{
4198 switch (srcBlend)
4199 {
4200 case GL_ZERO:
4201 case GL_ONE:
4202 case GL_SRC_COLOR:
4203 case GL_ONE_MINUS_SRC_COLOR:
4204 case GL_DST_COLOR:
4205 case GL_ONE_MINUS_DST_COLOR:
4206 case GL_SRC_ALPHA:
4207 case GL_ONE_MINUS_SRC_ALPHA:
4208 case GL_DST_ALPHA:
4209 case GL_ONE_MINUS_DST_ALPHA:
4210 case GL_CONSTANT_COLOR:
4211 case GL_ONE_MINUS_CONSTANT_COLOR:
4212 case GL_CONSTANT_ALPHA:
4213 case GL_ONE_MINUS_CONSTANT_ALPHA:
4214 case GL_SRC_ALPHA_SATURATE:
4215 return true;
4216
4217 default:
4218 return false;
4219 }
4220}
4221
4222static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4223{
4224 switch (dstBlend)
4225 {
4226 case GL_ZERO:
4227 case GL_ONE:
4228 case GL_SRC_COLOR:
4229 case GL_ONE_MINUS_SRC_COLOR:
4230 case GL_DST_COLOR:
4231 case GL_ONE_MINUS_DST_COLOR:
4232 case GL_SRC_ALPHA:
4233 case GL_ONE_MINUS_SRC_ALPHA:
4234 case GL_DST_ALPHA:
4235 case GL_ONE_MINUS_DST_ALPHA:
4236 case GL_CONSTANT_COLOR:
4237 case GL_ONE_MINUS_CONSTANT_COLOR:
4238 case GL_CONSTANT_ALPHA:
4239 case GL_ONE_MINUS_CONSTANT_ALPHA:
4240 return true;
4241
4242 case GL_SRC_ALPHA_SATURATE:
4243 return (contextMajorVersion >= 3);
4244
4245 default:
4246 return false;
4247 }
4248}
4249
4250bool ValidateBlendFuncSeparate(ValidationContext *context,
4251 GLenum srcRGB,
4252 GLenum dstRGB,
4253 GLenum srcAlpha,
4254 GLenum dstAlpha)
4255{
4256 if (!ValidSrcBlendFunc(srcRGB))
4257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004258 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004259 return false;
4260 }
4261
4262 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004264 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004265 return false;
4266 }
4267
4268 if (!ValidSrcBlendFunc(srcAlpha))
4269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004270 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004271 return false;
4272 }
4273
4274 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004276 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004277 return false;
4278 }
4279
Frank Henigman146e8a12017-03-02 23:22:37 -05004280 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4281 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004282 {
4283 bool constantColorUsed =
4284 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4285 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4286
4287 bool constantAlphaUsed =
4288 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4289 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4290
4291 if (constantColorUsed && constantAlphaUsed)
4292 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004293 const char *msg;
4294 if (context->getExtensions().webglCompatibility)
4295 {
4296 msg =
4297 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4298 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4299 }
4300 else
4301 {
4302 msg =
4303 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4304 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4305 "implementation.";
4306 ERR() << msg;
4307 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004308 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004309 return false;
4310 }
4311 }
4312
4313 return true;
4314}
4315
Geoff Langc339c4e2016-11-29 10:37:36 -05004316bool ValidateGetString(Context *context, GLenum name)
4317{
4318 switch (name)
4319 {
4320 case GL_VENDOR:
4321 case GL_RENDERER:
4322 case GL_VERSION:
4323 case GL_SHADING_LANGUAGE_VERSION:
4324 case GL_EXTENSIONS:
4325 break;
4326
4327 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4328 if (!context->getExtensions().requestExtension)
4329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004330 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004331 return false;
4332 }
4333 break;
4334
4335 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004336 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004337 return false;
4338 }
4339
4340 return true;
4341}
4342
Geoff Lang47c48082016-12-07 15:38:13 -05004343bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4344{
4345 if (width <= 0.0f || isNaN(width))
4346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004347 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004348 return false;
4349 }
4350
4351 return true;
4352}
4353
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004354bool ValidateVertexAttribPointer(ValidationContext *context,
4355 GLuint index,
4356 GLint size,
4357 GLenum type,
4358 GLboolean normalized,
4359 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004360 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004361{
Shao80957d92017-02-20 21:25:59 +08004362 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004363 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004364 return false;
4365 }
4366
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004367 if (stride < 0)
4368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004369 context->handleError(InvalidValue() << "stride cannot be negative.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004370 return false;
4371 }
4372
Shao80957d92017-02-20 21:25:59 +08004373 const Caps &caps = context->getCaps();
4374 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004375 {
Shao80957d92017-02-20 21:25:59 +08004376 if (stride > caps.maxVertexAttribStride)
4377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004378 context->handleError(InvalidValue()
4379 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004380 return false;
4381 }
4382
4383 if (index >= caps.maxVertexAttribBindings)
4384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004385 context->handleError(InvalidValue()
4386 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004387 return false;
4388 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004389 }
4390
4391 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4392 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4393 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4394 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004395 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4396 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004397 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004399 context
4400 ->handleError(InvalidOperation()
4401 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004402 return false;
4403 }
4404
4405 if (context->getExtensions().webglCompatibility)
4406 {
4407 // WebGL 1.0 [Section 6.14] Fixed point support
4408 // The WebGL API does not support the GL_FIXED data type.
4409 if (type == GL_FIXED)
4410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004411 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004412 return false;
4413 }
4414
Geoff Lang2d62ab72017-03-23 16:54:40 -04004415 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004416 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004417 return false;
4418 }
4419 }
4420
4421 return true;
4422}
4423
Jamie Madill876429b2017-04-20 15:46:24 -04004424bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004425{
4426 if (context->getExtensions().webglCompatibility && zNear > zFar)
4427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004428 context->handleError(InvalidOperation() << "Depth near > far.");
Frank Henigman6137ddc2017-02-10 18:55:07 -05004429 return false;
4430 }
4431
4432 return true;
4433}
4434
Jamie Madille8fb6402017-02-14 17:56:40 -05004435bool ValidateRenderbufferStorage(ValidationContext *context,
4436 GLenum target,
4437 GLenum internalformat,
4438 GLsizei width,
4439 GLsizei height)
4440{
4441 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4442 height);
4443}
4444
4445bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4446 GLenum target,
4447 GLsizei samples,
4448 GLenum internalformat,
4449 GLsizei width,
4450 GLsizei height)
4451{
4452 if (!context->getExtensions().framebufferMultisample)
4453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004454 context->handleError(InvalidOperation()
4455 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004456 return false;
4457 }
4458
4459 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4460 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4461 // generated.
4462 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004464 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004465 return false;
4466 }
4467
4468 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4469 // the specified storage. This is different than ES 3.0 in which a sample number higher
4470 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4471 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4472 if (context->getClientMajorVersion() >= 3)
4473 {
4474 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4475 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004477 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004478 return false;
4479 }
4480 }
4481
4482 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4483 width, height);
4484}
4485
Jamie Madillc1d770e2017-04-13 17:31:24 -04004486bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4487{
4488 if (!ValidFramebufferTarget(target))
4489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004490 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004491 return false;
4492 }
4493
4494 return true;
4495}
4496
4497bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004498 GLfloat red,
4499 GLfloat green,
4500 GLfloat blue,
4501 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004502{
4503 return true;
4504}
4505
Jamie Madill876429b2017-04-20 15:46:24 -04004506bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004507{
4508 return true;
4509}
4510
4511bool ValidateClearStencil(ValidationContext *context, GLint s)
4512{
4513 return true;
4514}
4515
4516bool ValidateColorMask(ValidationContext *context,
4517 GLboolean red,
4518 GLboolean green,
4519 GLboolean blue,
4520 GLboolean alpha)
4521{
4522 return true;
4523}
4524
4525bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4526{
4527 return true;
4528}
4529
4530bool ValidateCreateProgram(ValidationContext *context)
4531{
4532 return true;
4533}
4534
4535bool ValidateCullFace(ValidationContext *context, GLenum mode)
4536{
4537 switch (mode)
4538 {
4539 case GL_FRONT:
4540 case GL_BACK:
4541 case GL_FRONT_AND_BACK:
4542 break;
4543
4544 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004545 context->handleError(InvalidEnum() << "Invalid cull face parameter");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004546 return false;
4547 }
4548
4549 return true;
4550}
4551
4552bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4553{
4554 if (program == 0)
4555 {
4556 return false;
4557 }
4558
4559 if (!context->getProgram(program))
4560 {
4561 if (context->getShader(program))
4562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004563 context->handleError(InvalidOperation() << "Shader handle passed to DeleteProgram");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004564 return false;
4565 }
4566 else
4567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004568 context->handleError(InvalidValue() << "Invalid program handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004569 return false;
4570 }
4571 }
4572
4573 return true;
4574}
4575
4576bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4577{
4578 if (shader == 0)
4579 {
4580 return false;
4581 }
4582
4583 if (!context->getShader(shader))
4584 {
4585 if (context->getProgram(shader))
4586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004587 context->handleError(InvalidOperation() << "Program handle passed to DeleteShader");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004588 return false;
4589 }
4590 else
4591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004592 context->handleError(InvalidValue() << "Invalid shader handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004593 return false;
4594 }
4595 }
4596
4597 return true;
4598}
4599
4600bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4601{
4602 switch (func)
4603 {
4604 case GL_NEVER:
4605 case GL_ALWAYS:
4606 case GL_LESS:
4607 case GL_LEQUAL:
4608 case GL_EQUAL:
4609 case GL_GREATER:
4610 case GL_GEQUAL:
4611 case GL_NOTEQUAL:
4612 break;
4613
4614 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004615 context->handleError(InvalidEnum() << "Invalid depth function");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004616 return false;
4617 }
4618
4619 return true;
4620}
4621
4622bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4623{
4624 return true;
4625}
4626
4627bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4628{
4629 Program *programObject = GetValidProgram(context, program);
4630 if (!programObject)
4631 {
4632 return false;
4633 }
4634
4635 Shader *shaderObject = GetValidShader(context, shader);
4636 if (!shaderObject)
4637 {
4638 return false;
4639 }
4640
4641 const Shader *attachedShader = nullptr;
4642
4643 switch (shaderObject->getType())
4644 {
4645 case GL_VERTEX_SHADER:
4646 {
4647 attachedShader = programObject->getAttachedVertexShader();
4648 break;
4649 }
4650 case GL_FRAGMENT_SHADER:
4651 {
4652 attachedShader = programObject->getAttachedFragmentShader();
4653 break;
4654 }
4655 case GL_COMPUTE_SHADER:
4656 {
4657 attachedShader = programObject->getAttachedComputeShader();
4658 break;
4659 }
4660 default:
4661 UNREACHABLE();
4662 return false;
4663 }
4664
4665 if (attachedShader != shaderObject)
4666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004667 context->handleError(InvalidOperation() << "Cannot detach non-attached shader.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004668 return false;
4669 }
4670
4671 return true;
4672}
4673
4674bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4675{
4676 if (index >= MAX_VERTEX_ATTRIBS)
4677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004678 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004679 return false;
4680 }
4681
4682 return true;
4683}
4684
4685bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4686{
4687 if (index >= MAX_VERTEX_ATTRIBS)
4688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004689 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004690 return false;
4691 }
4692
4693 return true;
4694}
4695
4696bool ValidateFinish(ValidationContext *context)
4697{
4698 return true;
4699}
4700
4701bool ValidateFlush(ValidationContext *context)
4702{
4703 return true;
4704}
4705
4706bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4707{
4708 switch (mode)
4709 {
4710 case GL_CW:
4711 case GL_CCW:
4712 break;
4713 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004714 context->handleError(InvalidEnum() << "Invalid mode for FrontFace");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004715 return false;
4716 }
4717
4718 return true;
4719}
4720
4721bool ValidateGetActiveAttrib(ValidationContext *context,
4722 GLuint program,
4723 GLuint index,
4724 GLsizei bufsize,
4725 GLsizei *length,
4726 GLint *size,
4727 GLenum *type,
4728 GLchar *name)
4729{
4730 if (bufsize < 0)
4731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004732 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004733 return false;
4734 }
4735
4736 Program *programObject = GetValidProgram(context, program);
4737
4738 if (!programObject)
4739 {
4740 return false;
4741 }
4742
4743 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004745 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004746 return false;
4747 }
4748
4749 return true;
4750}
4751
4752bool ValidateGetActiveUniform(ValidationContext *context,
4753 GLuint program,
4754 GLuint index,
4755 GLsizei bufsize,
4756 GLsizei *length,
4757 GLint *size,
4758 GLenum *type,
4759 GLchar *name)
4760{
4761 if (bufsize < 0)
4762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004763 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004764 return false;
4765 }
4766
4767 Program *programObject = GetValidProgram(context, program);
4768
4769 if (!programObject)
4770 {
4771 return false;
4772 }
4773
4774 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004776 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004777 return false;
4778 }
4779
4780 return true;
4781}
4782
4783bool ValidateGetAttachedShaders(ValidationContext *context,
4784 GLuint program,
4785 GLsizei maxcount,
4786 GLsizei *count,
4787 GLuint *shaders)
4788{
4789 if (maxcount < 0)
4790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004791 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004792 return false;
4793 }
4794
4795 Program *programObject = GetValidProgram(context, program);
4796
4797 if (!programObject)
4798 {
4799 return false;
4800 }
4801
4802 return true;
4803}
4804
4805bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4806{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004807 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4808 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004809 if (context->getExtensions().webglCompatibility &&
4810 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004812 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004813 return false;
4814 }
4815
Jamie Madillc1d770e2017-04-13 17:31:24 -04004816 Program *programObject = GetValidProgram(context, program);
4817
4818 if (!programObject)
4819 {
4820 return false;
4821 }
4822
4823 if (!programObject->isLinked())
4824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004825 context->handleError(InvalidOperation() << "program not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004826 return false;
4827 }
4828
4829 return true;
4830}
4831
4832bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4833{
4834 GLenum nativeType;
4835 unsigned int numParams = 0;
4836 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4837}
4838
4839bool ValidateGetError(ValidationContext *context)
4840{
4841 return true;
4842}
4843
4844bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4845{
4846 GLenum nativeType;
4847 unsigned int numParams = 0;
4848 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4849}
4850
4851bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4852{
4853 GLenum nativeType;
4854 unsigned int numParams = 0;
4855 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4856}
4857
4858bool ValidateGetProgramInfoLog(ValidationContext *context,
4859 GLuint program,
4860 GLsizei bufsize,
4861 GLsizei *length,
4862 GLchar *infolog)
4863{
4864 if (bufsize < 0)
4865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004866 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004867 return false;
4868 }
4869
4870 Program *programObject = GetValidProgram(context, program);
4871 if (!programObject)
4872 {
4873 return false;
4874 }
4875
4876 return true;
4877}
4878
4879bool ValidateGetShaderInfoLog(ValidationContext *context,
4880 GLuint shader,
4881 GLsizei bufsize,
4882 GLsizei *length,
4883 GLchar *infolog)
4884{
4885 if (bufsize < 0)
4886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004887 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004888 return false;
4889 }
4890
4891 Shader *shaderObject = GetValidShader(context, shader);
4892 if (!shaderObject)
4893 {
4894 return false;
4895 }
4896
4897 return true;
4898}
4899
4900bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4901 GLenum shadertype,
4902 GLenum precisiontype,
4903 GLint *range,
4904 GLint *precision)
4905{
4906 switch (shadertype)
4907 {
4908 case GL_VERTEX_SHADER:
4909 case GL_FRAGMENT_SHADER:
4910 break;
4911 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004912 context->handleError(InvalidOperation()
4913 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004914 return false;
4915 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004916 context->handleError(InvalidEnum() << "invalid shader type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004917 return false;
4918 }
4919
4920 switch (precisiontype)
4921 {
4922 case GL_LOW_FLOAT:
4923 case GL_MEDIUM_FLOAT:
4924 case GL_HIGH_FLOAT:
4925 case GL_LOW_INT:
4926 case GL_MEDIUM_INT:
4927 case GL_HIGH_INT:
4928 break;
4929
4930 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004931 context->handleError(InvalidEnum() << "invalid precision type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004932 return false;
4933 }
4934
4935 return true;
4936}
4937
4938bool ValidateGetShaderSource(ValidationContext *context,
4939 GLuint shader,
4940 GLsizei bufsize,
4941 GLsizei *length,
4942 GLchar *source)
4943{
4944 if (bufsize < 0)
4945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004946 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004947 return false;
4948 }
4949
4950 Shader *shaderObject = GetValidShader(context, shader);
4951 if (!shaderObject)
4952 {
4953 return false;
4954 }
4955
4956 return true;
4957}
4958
4959bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4960{
4961 if (strstr(name, "gl_") == name)
4962 {
4963 return false;
4964 }
4965
Geoff Langfc32e8b2017-05-31 14:16:59 -04004966 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4967 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004968 if (context->getExtensions().webglCompatibility &&
4969 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004971 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004972 return false;
4973 }
4974
Jamie Madillc1d770e2017-04-13 17:31:24 -04004975 Program *programObject = GetValidProgram(context, program);
4976
4977 if (!programObject)
4978 {
4979 return false;
4980 }
4981
4982 if (!programObject->isLinked())
4983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004984 context->handleError(InvalidOperation() << "program is not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004985 return false;
4986 }
4987
4988 return true;
4989}
4990
4991bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4992{
4993 switch (mode)
4994 {
4995 case GL_FASTEST:
4996 case GL_NICEST:
4997 case GL_DONT_CARE:
4998 break;
4999
5000 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005001 context->handleError(InvalidEnum() << "invalid hint mode.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005002 return false;
5003 }
5004
5005 switch (target)
5006 {
5007 case GL_GENERATE_MIPMAP_HINT:
5008 break;
5009
Geoff Lange7bd2182017-06-16 16:13:13 -04005010 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5011 if (context->getClientVersion() < ES_3_0 &&
5012 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005014 context->handleError(InvalidOperation()
5015 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005016 return false;
5017 }
5018 break;
5019
5020 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005021 context->handleError(InvalidEnum() << "invalid hint target.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005022 return false;
5023 }
5024
5025 return true;
5026}
5027
5028bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5029{
5030 return true;
5031}
5032
5033bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5034{
5035 return true;
5036}
5037
5038bool ValidateIsProgram(ValidationContext *context, GLuint program)
5039{
5040 return true;
5041}
5042
5043bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5044{
5045 return true;
5046}
5047
5048bool ValidateIsShader(ValidationContext *context, GLuint shader)
5049{
5050 return true;
5051}
5052
5053bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5054{
5055 return true;
5056}
5057
5058bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5059{
5060 if (context->getClientMajorVersion() < 3)
5061 {
5062 switch (pname)
5063 {
5064 case GL_UNPACK_IMAGE_HEIGHT:
5065 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005066 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005067 return false;
5068
5069 case GL_UNPACK_ROW_LENGTH:
5070 case GL_UNPACK_SKIP_ROWS:
5071 case GL_UNPACK_SKIP_PIXELS:
5072 if (!context->getExtensions().unpackSubimage)
5073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005074 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005075 return false;
5076 }
5077 break;
5078
5079 case GL_PACK_ROW_LENGTH:
5080 case GL_PACK_SKIP_ROWS:
5081 case GL_PACK_SKIP_PIXELS:
5082 if (!context->getExtensions().packSubimage)
5083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005084 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005085 return false;
5086 }
5087 break;
5088 }
5089 }
5090
5091 if (param < 0)
5092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005093 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005094 return false;
5095 }
5096
5097 switch (pname)
5098 {
5099 case GL_UNPACK_ALIGNMENT:
5100 if (param != 1 && param != 2 && param != 4 && param != 8)
5101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005102 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005103 return false;
5104 }
5105 break;
5106
5107 case GL_PACK_ALIGNMENT:
5108 if (param != 1 && param != 2 && param != 4 && param != 8)
5109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005110 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005111 return false;
5112 }
5113 break;
5114
5115 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5116 case GL_UNPACK_ROW_LENGTH:
5117 case GL_UNPACK_IMAGE_HEIGHT:
5118 case GL_UNPACK_SKIP_IMAGES:
5119 case GL_UNPACK_SKIP_ROWS:
5120 case GL_UNPACK_SKIP_PIXELS:
5121 case GL_PACK_ROW_LENGTH:
5122 case GL_PACK_SKIP_ROWS:
5123 case GL_PACK_SKIP_PIXELS:
5124 break;
5125
5126 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005127 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005128 return false;
5129 }
5130
5131 return true;
5132}
5133
5134bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5135{
5136 return true;
5137}
5138
5139bool ValidateReleaseShaderCompiler(ValidationContext *context)
5140{
5141 return true;
5142}
5143
Jamie Madill876429b2017-04-20 15:46:24 -04005144bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005145{
5146 return true;
5147}
5148
5149bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5150{
5151 if (width < 0 || height < 0)
5152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005153 context->handleError(InvalidValue() << "Scissor width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005154 return false;
5155 }
5156
5157 return true;
5158}
5159
5160bool ValidateShaderBinary(ValidationContext *context,
5161 GLsizei n,
5162 const GLuint *shaders,
5163 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005164 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005165 GLsizei length)
5166{
5167 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5168 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5169 shaderBinaryFormats.end())
5170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005171 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005172 return false;
5173 }
5174
5175 return true;
5176}
5177
5178bool ValidateShaderSource(ValidationContext *context,
5179 GLuint shader,
5180 GLsizei count,
5181 const GLchar *const *string,
5182 const GLint *length)
5183{
5184 if (count < 0)
5185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005186 context->handleError(InvalidValue() << "Count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005187 return false;
5188 }
5189
Geoff Langfc32e8b2017-05-31 14:16:59 -04005190 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5191 // shader-related entry points
5192 if (context->getExtensions().webglCompatibility)
5193 {
5194 for (GLsizei i = 0; i < count; i++)
5195 {
5196 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005197
5198 // Backslash as line-continuation is allowed in WebGL 2.0.
5199 if (!IsValidESSLString(string[i], len, context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005201 context->handleError(InvalidValue() << "Shader source contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04005202 return false;
5203 }
5204 }
5205 }
5206
Jamie Madillc1d770e2017-04-13 17:31:24 -04005207 Shader *shaderObject = GetValidShader(context, shader);
5208 if (!shaderObject)
5209 {
5210 return false;
5211 }
5212
5213 return true;
5214}
5215
5216bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5217{
5218 if (!IsValidStencilFunc(func))
5219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005220 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005221 return false;
5222 }
5223
5224 return true;
5225}
5226
5227bool ValidateStencilFuncSeparate(ValidationContext *context,
5228 GLenum face,
5229 GLenum func,
5230 GLint ref,
5231 GLuint mask)
5232{
5233 if (!IsValidStencilFace(face))
5234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005235 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005236 return false;
5237 }
5238
5239 if (!IsValidStencilFunc(func))
5240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005241 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005242 return false;
5243 }
5244
5245 return true;
5246}
5247
5248bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5249{
5250 return true;
5251}
5252
5253bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5254{
5255 if (!IsValidStencilFace(face))
5256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005257 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005258 return false;
5259 }
5260
5261 return true;
5262}
5263
5264bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5265{
5266 if (!IsValidStencilOp(fail))
5267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005268 context->handleError(InvalidEnum() << "Invalid stencil fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005269 return false;
5270 }
5271
5272 if (!IsValidStencilOp(zfail))
5273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005274 context->handleError(InvalidEnum() << "Invalid stencil z fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005275 return false;
5276 }
5277
5278 if (!IsValidStencilOp(zpass))
5279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005280 context->handleError(InvalidEnum() << "Invalid stencil z pass op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005281 return false;
5282 }
5283
5284 return true;
5285}
5286
5287bool ValidateStencilOpSeparate(ValidationContext *context,
5288 GLenum face,
5289 GLenum fail,
5290 GLenum zfail,
5291 GLenum zpass)
5292{
5293 if (!IsValidStencilFace(face))
5294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005295 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005296 return false;
5297 }
5298
5299 return ValidateStencilOp(context, fail, zfail, zpass);
5300}
5301
5302bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5303{
5304 return ValidateUniform(context, GL_FLOAT, location, 1);
5305}
5306
5307bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5308{
5309 return ValidateUniform(context, GL_FLOAT, location, count);
5310}
5311
Jamie Madillbe849e42017-05-02 15:49:00 -04005312bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5313{
5314 return ValidateUniform1iv(context, location, 1, &x);
5315}
5316
Jamie Madillc1d770e2017-04-13 17:31:24 -04005317bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5318{
5319 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5320}
5321
5322bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5323{
5324 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5325}
5326
5327bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5328{
5329 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5330}
5331
5332bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5333{
5334 return ValidateUniform(context, GL_INT_VEC2, location, count);
5335}
5336
5337bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5338{
5339 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5340}
5341
5342bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5343{
5344 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5345}
5346
5347bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5348{
5349 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5350}
5351
5352bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5353{
5354 return ValidateUniform(context, GL_INT_VEC3, location, count);
5355}
5356
5357bool ValidateUniform4f(ValidationContext *context,
5358 GLint location,
5359 GLfloat x,
5360 GLfloat y,
5361 GLfloat z,
5362 GLfloat w)
5363{
5364 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5365}
5366
5367bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5368{
5369 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5370}
5371
5372bool ValidateUniform4i(ValidationContext *context,
5373 GLint location,
5374 GLint x,
5375 GLint y,
5376 GLint z,
5377 GLint w)
5378{
5379 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5380}
5381
5382bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5383{
5384 return ValidateUniform(context, GL_INT_VEC4, location, count);
5385}
5386
5387bool ValidateUniformMatrix2fv(ValidationContext *context,
5388 GLint location,
5389 GLsizei count,
5390 GLboolean transpose,
5391 const GLfloat *value)
5392{
5393 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5394}
5395
5396bool ValidateUniformMatrix3fv(ValidationContext *context,
5397 GLint location,
5398 GLsizei count,
5399 GLboolean transpose,
5400 const GLfloat *value)
5401{
5402 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5403}
5404
5405bool ValidateUniformMatrix4fv(ValidationContext *context,
5406 GLint location,
5407 GLsizei count,
5408 GLboolean transpose,
5409 const GLfloat *value)
5410{
5411 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5412}
5413
5414bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5415{
5416 Program *programObject = GetValidProgram(context, program);
5417
5418 if (!programObject)
5419 {
5420 return false;
5421 }
5422
5423 return true;
5424}
5425
5426bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5427{
5428 if (index >= MAX_VERTEX_ATTRIBS)
5429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005430 context->handleError(InvalidValue() << "Vertex attrib index out of range.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005431 return false;
5432 }
5433
5434 return true;
5435}
5436
5437bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5438{
5439 return ValidateVertexAttribIndex(context, index);
5440}
5441
5442bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5443{
5444 return ValidateVertexAttribIndex(context, index);
5445}
5446
5447bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5448{
5449 return ValidateVertexAttribIndex(context, index);
5450}
5451
5452bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5453{
5454 return ValidateVertexAttribIndex(context, index);
5455}
5456
5457bool ValidateVertexAttrib3f(ValidationContext *context,
5458 GLuint index,
5459 GLfloat x,
5460 GLfloat y,
5461 GLfloat z)
5462{
5463 return ValidateVertexAttribIndex(context, index);
5464}
5465
5466bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5467{
5468 return ValidateVertexAttribIndex(context, index);
5469}
5470
5471bool ValidateVertexAttrib4f(ValidationContext *context,
5472 GLuint index,
5473 GLfloat x,
5474 GLfloat y,
5475 GLfloat z,
5476 GLfloat w)
5477{
5478 return ValidateVertexAttribIndex(context, index);
5479}
5480
5481bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5482{
5483 return ValidateVertexAttribIndex(context, index);
5484}
5485
5486bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5487{
5488 if (width < 0 || height < 0)
5489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005490 context->handleError(InvalidValue() << "Viewport width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005491 return false;
5492 }
5493
5494 return true;
5495}
5496
5497bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5498{
5499 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5500}
5501
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005502bool ValidateDrawElements(ValidationContext *context,
5503 GLenum mode,
5504 GLsizei count,
5505 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005506 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005507{
5508 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5509}
5510
Jamie Madillbe849e42017-05-02 15:49:00 -04005511bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5512 GLenum target,
5513 GLenum attachment,
5514 GLenum pname,
5515 GLint *params)
5516{
5517 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5518 nullptr);
5519}
5520
5521bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5522{
5523 return ValidateGetProgramivBase(context, program, pname, nullptr);
5524}
5525
5526bool ValidateCopyTexImage2D(ValidationContext *context,
5527 GLenum target,
5528 GLint level,
5529 GLenum internalformat,
5530 GLint x,
5531 GLint y,
5532 GLsizei width,
5533 GLsizei height,
5534 GLint border)
5535{
5536 if (context->getClientMajorVersion() < 3)
5537 {
5538 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5539 0, x, y, width, height, border);
5540 }
5541
5542 ASSERT(context->getClientMajorVersion() == 3);
5543 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5544 0, x, y, width, height, border);
5545}
5546
5547bool ValidateCopyTexSubImage2D(Context *context,
5548 GLenum target,
5549 GLint level,
5550 GLint xoffset,
5551 GLint yoffset,
5552 GLint x,
5553 GLint y,
5554 GLsizei width,
5555 GLsizei height)
5556{
5557 if (context->getClientMajorVersion() < 3)
5558 {
5559 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5560 yoffset, x, y, width, height, 0);
5561 }
5562
5563 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5564 yoffset, 0, x, y, width, height, 0);
5565}
5566
5567bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5568{
5569 return ValidateGenOrDelete(context, n);
5570}
5571
5572bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5573{
5574 return ValidateGenOrDelete(context, n);
5575}
5576
5577bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5578{
5579 return ValidateGenOrDelete(context, n);
5580}
5581
5582bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5583{
5584 return ValidateGenOrDelete(context, n);
5585}
5586
5587bool ValidateDisable(Context *context, GLenum cap)
5588{
5589 if (!ValidCap(context, cap, false))
5590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005591 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005592 return false;
5593 }
5594
5595 return true;
5596}
5597
5598bool ValidateEnable(Context *context, GLenum cap)
5599{
5600 if (!ValidCap(context, cap, false))
5601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005602 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005603 return false;
5604 }
5605
5606 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5607 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5608 {
5609 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005610 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005611
5612 // We also output an error message to the debugger window if tracing is active, so that
5613 // developers can see the error message.
5614 ERR() << errorMessage;
5615 return false;
5616 }
5617
5618 return true;
5619}
5620
5621bool ValidateFramebufferRenderbuffer(Context *context,
5622 GLenum target,
5623 GLenum attachment,
5624 GLenum renderbuffertarget,
5625 GLuint renderbuffer)
5626{
5627 if (!ValidFramebufferTarget(target) ||
5628 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005630 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005631 return false;
5632 }
5633
5634 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5635 renderbuffertarget, renderbuffer);
5636}
5637
5638bool ValidateFramebufferTexture2D(Context *context,
5639 GLenum target,
5640 GLenum attachment,
5641 GLenum textarget,
5642 GLuint texture,
5643 GLint level)
5644{
5645 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5646 // extension
5647 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5648 level != 0)
5649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005650 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005651 return false;
5652 }
5653
5654 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5655 {
5656 return false;
5657 }
5658
5659 if (texture != 0)
5660 {
5661 gl::Texture *tex = context->getTexture(texture);
5662 ASSERT(tex);
5663
5664 const gl::Caps &caps = context->getCaps();
5665
5666 switch (textarget)
5667 {
5668 case GL_TEXTURE_2D:
5669 {
5670 if (level > gl::log2(caps.max2DTextureSize))
5671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005672 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 return false;
5674 }
5675 if (tex->getTarget() != GL_TEXTURE_2D)
5676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005677 context->handleError(InvalidOperation()
5678 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005679 return false;
5680 }
5681 }
5682 break;
5683
5684 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5688 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5689 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5690 {
5691 if (level > gl::log2(caps.maxCubeMapTextureSize))
5692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005693 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 return false;
5695 }
5696 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005698 context->handleError(InvalidOperation()
5699 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 return false;
5701 }
5702 }
5703 break;
5704
5705 case GL_TEXTURE_2D_MULTISAMPLE:
5706 {
5707 if (context->getClientVersion() < ES_3_1)
5708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005709 context->handleError(InvalidOperation()
5710 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005711 return false;
5712 }
5713
5714 if (level != 0)
5715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005716 context->handleError(InvalidValue()
5717 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005722 context->handleError(InvalidOperation()
5723 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005724 return false;
5725 }
5726 }
5727 break;
5728
5729 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005730 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005731 return false;
5732 }
5733
5734 const Format &format = tex->getFormat(textarget, level);
5735 if (format.info->compressed)
5736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005737 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005738 return false;
5739 }
5740 }
5741
5742 return true;
5743}
5744
5745bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5746{
5747 return ValidateGenOrDelete(context, n);
5748}
5749
5750bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5751{
5752 return ValidateGenOrDelete(context, n);
5753}
5754
5755bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5756{
5757 return ValidateGenOrDelete(context, n);
5758}
5759
5760bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5761{
5762 return ValidateGenOrDelete(context, n);
5763}
5764
5765bool ValidateGenerateMipmap(Context *context, GLenum target)
5766{
5767 if (!ValidTextureTarget(context, target))
5768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005769 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005770 return false;
5771 }
5772
5773 Texture *texture = context->getTargetTexture(target);
5774
5775 if (texture == nullptr)
5776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005777 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005778 return false;
5779 }
5780
5781 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5782
5783 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5784 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5785 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005787 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005788 return false;
5789 }
5790
5791 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5792 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5793 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5794
5795 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5796 // unsized formats or that are color renderable and filterable. Since we do not track if
5797 // the texture was created with sized or unsized format (only sized formats are stored),
5798 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5799 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5800 // textures since they're the only texture format that can be created with unsized formats
5801 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5802 // was the last version to use add them.
5803 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5804 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005806 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809
Geoff Lang65ac5b92017-05-01 13:16:30 -04005810 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5811 bool supportsSRGBMipmapGeneration =
5812 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5813 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005815 context->handleError(InvalidOperation()
5816 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005817 return false;
5818 }
5819
5820 // Non-power of 2 ES2 check
5821 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5822 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5823 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5824 {
5825 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005826 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 return false;
5828 }
5829
5830 // Cube completeness check
5831 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005833 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005834 return false;
5835 }
5836
5837 return true;
5838}
5839
5840bool ValidateGetBufferParameteriv(ValidationContext *context,
5841 GLenum target,
5842 GLenum pname,
5843 GLint *params)
5844{
5845 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5846}
5847
5848bool ValidateGetRenderbufferParameteriv(Context *context,
5849 GLenum target,
5850 GLenum pname,
5851 GLint *params)
5852{
5853 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5854}
5855
5856bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5857{
5858 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5859}
5860
5861bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5862{
5863 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5864}
5865
5866bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5867{
5868 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5869}
5870
5871bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5872{
5873 return ValidateGetUniformBase(context, program, location);
5874}
5875
5876bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5877{
5878 return ValidateGetUniformBase(context, program, location);
5879}
5880
5881bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5882{
5883 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5884}
5885
5886bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5887{
5888 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5889}
5890
5891bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5892{
5893 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5894}
5895
5896bool ValidateIsEnabled(Context *context, GLenum cap)
5897{
5898 if (!ValidCap(context, cap, true))
5899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005900 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005901 return false;
5902 }
5903
5904 return true;
5905}
5906
5907bool ValidateLinkProgram(Context *context, GLuint program)
5908{
5909 if (context->hasActiveTransformFeedback(program))
5910 {
5911 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005912 context->handleError(InvalidOperation() << "Cannot link program while program is "
5913 "associated with an active transform "
5914 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005915 return false;
5916 }
5917
5918 Program *programObject = GetValidProgram(context, program);
5919 if (!programObject)
5920 {
5921 return false;
5922 }
5923
5924 return true;
5925}
5926
Jamie Madill4928b7c2017-06-20 12:57:39 -04005927bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005928 GLint x,
5929 GLint y,
5930 GLsizei width,
5931 GLsizei height,
5932 GLenum format,
5933 GLenum type,
5934 void *pixels)
5935{
5936 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5937 nullptr, pixels);
5938}
5939
5940bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5941{
5942 return ValidateTexParameterBase(context, target, pname, -1, &param);
5943}
5944
5945bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5946{
5947 return ValidateTexParameterBase(context, target, pname, -1, params);
5948}
5949
5950bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5951{
5952 return ValidateTexParameterBase(context, target, pname, -1, &param);
5953}
5954
5955bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5956{
5957 return ValidateTexParameterBase(context, target, pname, -1, params);
5958}
5959
5960bool ValidateUseProgram(Context *context, GLuint program)
5961{
5962 if (program != 0)
5963 {
5964 Program *programObject = context->getProgram(program);
5965 if (!programObject)
5966 {
5967 // ES 3.1.0 section 7.3 page 72
5968 if (context->getShader(program))
5969 {
5970 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005971 InvalidOperation()
5972 << "Attempted to use a single shader instead of a shader program.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005973 return false;
5974 }
5975 else
5976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005977 context->handleError(InvalidValue() << "Program invalid.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005978 return false;
5979 }
5980 }
5981 if (!programObject->isLinked())
5982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005983 context->handleError(InvalidOperation() << "Program not linked.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005984 return false;
5985 }
5986 }
5987 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5988 {
5989 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005990 context
5991 ->handleError(InvalidOperation()
5992 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005993 return false;
5994 }
5995
5996 return true;
5997}
5998
Jamie Madillc29968b2016-01-20 11:17:23 -05005999} // namespace gl