blob: 08fbc501b04d7a46f6e75544f4a4dde616fdf6ca [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
235bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
236{
237 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
238}
239
240bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
241{
242 // Table 1.0 from the CHROMIUM_copy_texture spec
243 switch (internalFormat)
244 {
245 case GL_RGB:
246 case GL_RGBA:
247 case GL_RGB8:
248 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700249 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400250 case GL_BGRA8_EXT:
251 case GL_SRGB_EXT:
252 case GL_SRGB_ALPHA_EXT:
253 case GL_R8:
254 case GL_R8UI:
255 case GL_RG8:
256 case GL_RG8UI:
257 case GL_SRGB8:
258 case GL_RGB565:
259 case GL_RGB8UI:
260 case GL_SRGB8_ALPHA8:
261 case GL_RGB5_A1:
262 case GL_RGBA4:
263 case GL_RGBA8UI:
264 case GL_RGB9_E5:
265 case GL_R16F:
266 case GL_R32F:
267 case GL_RG16F:
268 case GL_RG32F:
269 case GL_RGB16F:
270 case GL_RGB32F:
271 case GL_RGBA16F:
272 case GL_RGBA32F:
273 case GL_R11F_G11F_B10F:
274 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700275
276 default:
277 return false;
278 }
279}
280
281bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
282{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400283 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700284 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400285 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700286 }
287
Geoff Lang4f0e0032017-05-01 16:04:35 -0400288 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
289 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700290 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400291 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700292 }
293
294 return true;
295}
296
Geoff Lang4f0e0032017-05-01 16:04:35 -0400297bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700298{
299 switch (target)
300 {
301 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400302 return textureType == GL_TEXTURE_2D;
303
304 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
305 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
306 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
307 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
308 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
309 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
310 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700311
312 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
313 // supported
314
315 default:
316 return false;
317 }
318}
319
320bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
321{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400322 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700323 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400324 case GL_TEXTURE_2D:
325 return true;
326
327 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
328 // supported
329
330 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
331 // supported
332
333 default:
334 return false;
335 }
336}
337
338bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
339{
340 if (level < 0)
341 {
342 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700343 }
344
Geoff Lang4f0e0032017-05-01 16:04:35 -0400345 if (level > 0 && context->getClientVersion() < ES_3_0)
346 {
347 return false;
348 }
Geoff Lang97073d12016-04-20 10:42:34 -0700349
Geoff Lang4f0e0032017-05-01 16:04:35 -0400350 return true;
351}
352
353bool IsValidCopyTextureDestinationLevel(Context *context,
354 GLenum target,
355 GLint level,
356 GLsizei width,
357 GLsizei height)
358{
359 if (level < 0)
360 {
361 return false;
362 }
363
Geoff Lang4f0e0032017-05-01 16:04:35 -0400364 const Caps &caps = context->getCaps();
365 if (target == GL_TEXTURE_2D)
366 {
367 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
368 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
369 {
370 return false;
371 }
372 }
373 else if (IsCubeMapTextureTarget(target))
374 {
375 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
376 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
377 {
378 return false;
379 }
380 }
381
382 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700383}
384
Jamie Madillc1d770e2017-04-13 17:31:24 -0400385bool IsValidStencilFunc(GLenum func)
386{
387 switch (func)
388 {
389 case GL_NEVER:
390 case GL_ALWAYS:
391 case GL_LESS:
392 case GL_LEQUAL:
393 case GL_EQUAL:
394 case GL_GEQUAL:
395 case GL_GREATER:
396 case GL_NOTEQUAL:
397 return true;
398
399 default:
400 return false;
401 }
402}
403
404bool IsValidStencilFace(GLenum face)
405{
406 switch (face)
407 {
408 case GL_FRONT:
409 case GL_BACK:
410 case GL_FRONT_AND_BACK:
411 return true;
412
413 default:
414 return false;
415 }
416}
417
418bool IsValidStencilOp(GLenum op)
419{
420 switch (op)
421 {
422 case GL_ZERO:
423 case GL_KEEP:
424 case GL_REPLACE:
425 case GL_INCR:
426 case GL_DECR:
427 case GL_INVERT:
428 case GL_INCR_WRAP:
429 case GL_DECR_WRAP:
430 return true;
431
432 default:
433 return false;
434 }
435}
436
Jamie Madillbe849e42017-05-02 15:49:00 -0400437bool ValidateES2CopyTexImageParameters(ValidationContext *context,
438 GLenum target,
439 GLint level,
440 GLenum internalformat,
441 bool isSubImage,
442 GLint xoffset,
443 GLint yoffset,
444 GLint x,
445 GLint y,
446 GLsizei width,
447 GLsizei height,
448 GLint border)
449{
450 if (!ValidTexture2DDestinationTarget(context, target))
451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500452 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -0400453 return false;
454 }
455
456 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500458 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400459 return false;
460 }
461
462 Format textureFormat = Format::Invalid();
463 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
464 xoffset, yoffset, 0, x, y, width, height, border,
465 &textureFormat))
466 {
467 return false;
468 }
469
470 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
471 GLenum colorbufferFormat =
472 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
473 const auto &formatInfo = *textureFormat.info;
474
475 // [OpenGL ES 2.0.24] table 3.9
476 if (isSubImage)
477 {
478 switch (formatInfo.format)
479 {
480 case GL_ALPHA:
481 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400482 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
483 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500485 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400486 return false;
487 }
488 break;
489 case GL_LUMINANCE:
490 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
491 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
492 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400493 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
494 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500496 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400497 return false;
498 }
499 break;
500 case GL_RED_EXT:
501 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
502 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
503 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
504 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
505 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400506 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
507 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500509 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400510 return false;
511 }
512 break;
513 case GL_RG_EXT:
514 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
515 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
516 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
517 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400518 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
519 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500521 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400522 return false;
523 }
524 break;
525 case GL_RGB:
526 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
527 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
528 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400529 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
530 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500532 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400533 return false;
534 }
535 break;
536 case GL_LUMINANCE_ALPHA:
537 case GL_RGBA:
538 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400539 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
540 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500542 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400543 return false;
544 }
545 break;
546 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
547 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
548 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
549 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
550 case GL_ETC1_RGB8_OES:
551 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
552 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
553 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
554 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
555 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500556 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400557 return false;
558 case GL_DEPTH_COMPONENT:
559 case GL_DEPTH_STENCIL_OES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500560 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400561 return false;
562 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500563 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400564 return false;
565 }
566
567 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500569 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400570 return false;
571 }
572 }
573 else
574 {
575 switch (internalformat)
576 {
577 case GL_ALPHA:
578 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
579 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
580 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500582 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400583 return false;
584 }
585 break;
586 case GL_LUMINANCE:
587 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
588 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
589 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
590 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
591 colorbufferFormat != GL_BGR5_A1_ANGLEX)
592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500593 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400594 return false;
595 }
596 break;
597 case GL_RED_EXT:
598 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
599 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
600 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
601 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
602 colorbufferFormat != GL_BGR5_A1_ANGLEX)
603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500604 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400605 return false;
606 }
607 break;
608 case GL_RG_EXT:
609 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
610 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
611 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
612 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500614 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400615 return false;
616 }
617 break;
618 case GL_RGB:
619 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
620 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
621 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
622 colorbufferFormat != GL_BGR5_A1_ANGLEX)
623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500624 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400625 return false;
626 }
627 break;
628 case GL_LUMINANCE_ALPHA:
629 case GL_RGBA:
630 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
631 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
632 colorbufferFormat != GL_BGR5_A1_ANGLEX)
633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500634 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 return false;
636 }
637 break;
638 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
639 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
640 if (context->getExtensions().textureCompressionDXT1)
641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500642 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400643 return false;
644 }
645 else
646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500647 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400648 return false;
649 }
650 break;
651 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
652 if (context->getExtensions().textureCompressionDXT3)
653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500654 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400655 return false;
656 }
657 else
658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500659 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400660 return false;
661 }
662 break;
663 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
664 if (context->getExtensions().textureCompressionDXT5)
665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500666 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400667 return false;
668 }
669 else
670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500671 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400672 return false;
673 }
674 break;
675 case GL_ETC1_RGB8_OES:
676 if (context->getExtensions().compressedETC1RGB8Texture)
677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500678 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400679 return false;
680 }
681 else
682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500683 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400684 return false;
685 }
686 break;
687 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
688 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
689 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
690 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
691 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
692 if (context->getExtensions().lossyETCDecode)
693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500694 context->handleError(InvalidOperation()
695 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400696 return false;
697 }
698 else
699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500700 context->handleError(InvalidEnum()
701 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400702 return false;
703 }
704 break;
705 case GL_DEPTH_COMPONENT:
706 case GL_DEPTH_COMPONENT16:
707 case GL_DEPTH_COMPONENT32_OES:
708 case GL_DEPTH_STENCIL_OES:
709 case GL_DEPTH24_STENCIL8_OES:
710 if (context->getExtensions().depthTextures)
711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500712 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400713 return false;
714 }
715 else
716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500717 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400718 return false;
719 }
720 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500721 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400722 return false;
723 }
724 }
725
726 // If width or height is zero, it is a no-op. Return false without setting an error.
727 return (width > 0 && height > 0);
728}
729
730bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
731{
732 switch (cap)
733 {
734 // EXT_multisample_compatibility
735 case GL_MULTISAMPLE_EXT:
736 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
737 return context->getExtensions().multisampleCompatibility;
738
739 case GL_CULL_FACE:
740 case GL_POLYGON_OFFSET_FILL:
741 case GL_SAMPLE_ALPHA_TO_COVERAGE:
742 case GL_SAMPLE_COVERAGE:
743 case GL_SCISSOR_TEST:
744 case GL_STENCIL_TEST:
745 case GL_DEPTH_TEST:
746 case GL_BLEND:
747 case GL_DITHER:
748 return true;
749
750 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
751 case GL_RASTERIZER_DISCARD:
752 return (context->getClientMajorVersion() >= 3);
753
754 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
755 case GL_DEBUG_OUTPUT:
756 return context->getExtensions().debug;
757
758 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
759 return queryOnly && context->getExtensions().bindGeneratesResource;
760
761 case GL_CLIENT_ARRAYS_ANGLE:
762 return queryOnly && context->getExtensions().clientArrays;
763
764 case GL_FRAMEBUFFER_SRGB_EXT:
765 return context->getExtensions().sRGBWriteControl;
766
767 case GL_SAMPLE_MASK:
768 return context->getClientVersion() >= Version(3, 1);
769
770 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
771 return queryOnly && context->getExtensions().robustResourceInitialization;
772
773 default:
774 return false;
775 }
776}
777
Geoff Langfc32e8b2017-05-31 14:16:59 -0400778// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
779// 3.1.
780bool IsValidESSLCharacter(unsigned char c)
781{
782 // Printing characters are valid except " $ ` @ \ ' DEL.
783 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
784 c != '\'')
785 {
786 return true;
787 }
788
789 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
790 if (c >= 9 && c <= 13)
791 {
792 return true;
793 }
794
795 return false;
796}
797
798bool IsValidESSLString(const char *str, size_t len)
799{
800 return len == 0 || std::find_if_not(str, str + len, IsValidESSLCharacter) == str + len;
801}
802
Jamie Madillc29968b2016-01-20 11:17:23 -0500803} // anonymous namespace
804
Geoff Langff5b2d52016-09-07 11:32:23 -0400805bool ValidateES2TexImageParameters(Context *context,
806 GLenum target,
807 GLint level,
808 GLenum internalformat,
809 bool isCompressed,
810 bool isSubImage,
811 GLint xoffset,
812 GLint yoffset,
813 GLsizei width,
814 GLsizei height,
815 GLint border,
816 GLenum format,
817 GLenum type,
818 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400819 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820{
Jamie Madill6f38f822014-06-06 17:12:20 -0400821 if (!ValidTexture2DDestinationTarget(context, target))
822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500823 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400824 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400825 }
826
Austin Kinross08528e12015-10-07 16:24:40 -0700827 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500829 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400830 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 }
832
He Yunchaoced53ae2016-11-29 15:00:51 +0800833 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 std::numeric_limits<GLsizei>::max() - yoffset < height)
835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500836 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400837 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 }
839
Geoff Lang6e898aa2017-06-02 11:17:26 -0400840 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
841 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
842 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
843 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
844 // case.
845 bool nonEqualFormatsAllowed =
846 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
847 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
848
849 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500851 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400852 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 }
854
Geoff Langaae65a42014-05-26 12:43:44 -0400855 const gl::Caps &caps = context->getCaps();
856
Geoff Langa9be0dc2014-12-17 12:34:40 -0500857 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500859 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
860 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500862 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500863 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400864 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500865 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500866 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500867 {
868 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500870 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500871 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400872 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400873
Geoff Langa9be0dc2014-12-17 12:34:40 -0500874 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
875 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500877 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500878 return false;
879 }
880 }
881 else
882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500883 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400884 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400885 }
886
He Yunchaoced53ae2016-11-29 15:00:51 +0800887 gl::Texture *texture =
888 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400889 if (!texture)
890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400892 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 }
894
Geoff Langa9be0dc2014-12-17 12:34:40 -0500895 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400896 {
Geoff Langca271392017-04-05 12:30:00 -0400897 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
898 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500900 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500901 return false;
902 }
903
Geoff Langa9be0dc2014-12-17 12:34:40 -0500904 if (format != GL_NONE)
905 {
Geoff Langca271392017-04-05 12:30:00 -0400906 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
907 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500909 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500910 return false;
911 }
912 }
913
914 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
915 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500917 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500918 return false;
919 }
920 }
921 else
922 {
Geoff Lang69cce582015-09-17 13:20:36 -0400923 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500925 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500926 return false;
927 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928 }
929
930 // Verify zero border
931 if (border != 0)
932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500933 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400934 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 }
936
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 if (isCompressed)
938 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400939 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400940 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
941 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 switch (actualInternalFormat)
943 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800944 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
945 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
946 if (!context->getExtensions().textureCompressionDXT1)
947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500948 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800949 return false;
950 }
951 break;
952 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
953 if (!context->getExtensions().textureCompressionDXT1)
954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500955 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800956 return false;
957 }
958 break;
959 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
960 if (!context->getExtensions().textureCompressionDXT5)
961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800963 return false;
964 }
965 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800966 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
967 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
968 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
969 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
970 if (!context->getExtensions().textureCompressionS3TCsRGB)
971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500972 context->handleError(InvalidEnum());
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800973 return false;
974 }
975 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800976 case GL_ETC1_RGB8_OES:
977 if (!context->getExtensions().compressedETC1RGB8Texture)
978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500979 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 return false;
981 }
982 break;
983 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800984 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
985 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
986 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
987 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800988 if (!context->getExtensions().lossyETCDecode)
989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500990 context->handleError(InvalidEnum()
991 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 return false;
993 }
994 break;
995 default:
996 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500997 InvalidEnum()
998 << "internalformat is not a supported compressed internal format");
Geoff Langb1196682014-07-23 13:47:29 -0400999 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001000 }
Geoff Lang966c9402017-04-18 12:38:27 -04001001
1002 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001003 {
Geoff Lang966c9402017-04-18 12:38:27 -04001004 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1005 height, texture->getWidth(target, level),
1006 texture->getHeight(target, level)))
1007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001009 return false;
1010 }
1011
1012 if (format != actualInternalFormat)
1013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001014 context->handleError(InvalidOperation()
1015 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -04001016 return false;
1017 }
1018 }
1019 else
1020 {
1021 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001023 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001024 return false;
1025 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001026 }
1027 }
1028 else
1029 {
1030 // validate <type> by itself (used as secondary key below)
1031 switch (type)
1032 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001033 case GL_UNSIGNED_BYTE:
1034 case GL_UNSIGNED_SHORT_5_6_5:
1035 case GL_UNSIGNED_SHORT_4_4_4_4:
1036 case GL_UNSIGNED_SHORT_5_5_5_1:
1037 case GL_UNSIGNED_SHORT:
1038 case GL_UNSIGNED_INT:
1039 case GL_UNSIGNED_INT_24_8_OES:
1040 case GL_HALF_FLOAT_OES:
1041 case GL_FLOAT:
1042 break;
1043 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001044 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001045 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 }
1047
1048 // validate <format> + <type> combinations
1049 // - invalid <format> -> sets INVALID_ENUM
1050 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1051 switch (format)
1052 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001053 case GL_ALPHA:
1054 case GL_LUMINANCE:
1055 case GL_LUMINANCE_ALPHA:
1056 switch (type)
1057 {
1058 case GL_UNSIGNED_BYTE:
1059 case GL_FLOAT:
1060 case GL_HALF_FLOAT_OES:
1061 break;
1062 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001063 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001064 return false;
1065 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001066 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001067 case GL_RED:
1068 case GL_RG:
1069 if (!context->getExtensions().textureRG)
1070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001071 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 return false;
1073 }
1074 switch (type)
1075 {
1076 case GL_UNSIGNED_BYTE:
1077 case GL_FLOAT:
1078 case GL_HALF_FLOAT_OES:
1079 break;
1080 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001081 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001082 return false;
1083 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001084 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001085 case GL_RGB:
1086 switch (type)
1087 {
1088 case GL_UNSIGNED_BYTE:
1089 case GL_UNSIGNED_SHORT_5_6_5:
1090 case GL_FLOAT:
1091 case GL_HALF_FLOAT_OES:
1092 break;
1093 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001094 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001095 return false;
1096 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 case GL_RGBA:
1099 switch (type)
1100 {
1101 case GL_UNSIGNED_BYTE:
1102 case GL_UNSIGNED_SHORT_4_4_4_4:
1103 case GL_UNSIGNED_SHORT_5_5_5_1:
1104 case GL_FLOAT:
1105 case GL_HALF_FLOAT_OES:
1106 break;
1107 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001108 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001109 return false;
1110 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001112 case GL_BGRA_EXT:
1113 switch (type)
1114 {
1115 case GL_UNSIGNED_BYTE:
1116 break;
1117 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001118 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001119 return false;
1120 }
1121 break;
1122 case GL_SRGB_EXT:
1123 case GL_SRGB_ALPHA_EXT:
1124 if (!context->getExtensions().sRGB)
1125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001126 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 return false;
1128 }
1129 switch (type)
1130 {
1131 case GL_UNSIGNED_BYTE:
1132 break;
1133 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001135 return false;
1136 }
1137 break;
1138 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1139 // handled below
1140 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1141 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1142 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1143 break;
1144 case GL_DEPTH_COMPONENT:
1145 switch (type)
1146 {
1147 case GL_UNSIGNED_SHORT:
1148 case GL_UNSIGNED_INT:
1149 break;
1150 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001151 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001152 return false;
1153 }
1154 break;
1155 case GL_DEPTH_STENCIL_OES:
1156 switch (type)
1157 {
1158 case GL_UNSIGNED_INT_24_8_OES:
1159 break;
1160 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001161 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001162 return false;
1163 }
1164 break;
1165 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001166 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001167 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 }
1169
1170 switch (format)
1171 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001172 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1173 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1174 if (context->getExtensions().textureCompressionDXT1)
1175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001176 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 return false;
1178 }
1179 else
1180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001181 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001182 return false;
1183 }
1184 break;
1185 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1186 if (context->getExtensions().textureCompressionDXT3)
1187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001188 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001189 return false;
1190 }
1191 else
1192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 return false;
1195 }
1196 break;
1197 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1198 if (context->getExtensions().textureCompressionDXT5)
1199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001200 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001201 return false;
1202 }
1203 else
1204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001205 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return false;
1207 }
1208 break;
1209 case GL_ETC1_RGB8_OES:
1210 if (context->getExtensions().compressedETC1RGB8Texture)
1211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001212 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001213 return false;
1214 }
1215 else
1216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001217 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 return false;
1219 }
1220 break;
1221 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001222 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1223 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1224 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1225 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001226 if (context->getExtensions().lossyETCDecode)
1227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001228 context->handleError(InvalidOperation()
1229 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001230 return false;
1231 }
1232 else
1233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001234 context->handleError(InvalidEnum()
1235 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001236 return false;
1237 }
1238 break;
1239 case GL_DEPTH_COMPONENT:
1240 case GL_DEPTH_STENCIL_OES:
1241 if (!context->getExtensions().depthTextures)
1242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001243 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001244 return false;
1245 }
1246 if (target != GL_TEXTURE_2D)
1247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001249 return false;
1250 }
1251 // OES_depth_texture supports loading depth data and multiple levels,
1252 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001253 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001256 return false;
1257 }
1258 break;
1259 default:
1260 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 }
1262
Geoff Lang6e898aa2017-06-02 11:17:26 -04001263 if (!isSubImage)
1264 {
1265 switch (internalformat)
1266 {
1267 case GL_RGBA32F:
1268 if (!context->getExtensions().colorBufferFloatRGBA)
1269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidValue()
1271 << "Sized GL_RGBA32F internal format requires "
1272 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001273 return false;
1274 }
1275 if (type != GL_FLOAT)
1276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001277 context->handleError(InvalidOperation()
1278 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001279 return false;
1280 }
1281 if (format != GL_RGBA)
1282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001283 context->handleError(InvalidOperation()
1284 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001285 return false;
1286 }
1287 break;
1288
1289 case GL_RGB32F:
1290 if (!context->getExtensions().colorBufferFloatRGB)
1291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001292 context->handleError(InvalidValue()
1293 << "Sized GL_RGB32F internal format requires "
1294 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001295 return false;
1296 }
1297 if (type != GL_FLOAT)
1298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001299 context->handleError(InvalidOperation()
1300 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001301 return false;
1302 }
1303 if (format != GL_RGB)
1304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001305 context->handleError(InvalidOperation()
1306 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001307 return false;
1308 }
1309 break;
1310
1311 default:
1312 break;
1313 }
1314 }
1315
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316 if (type == GL_FLOAT)
1317 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001318 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322 }
1323 }
1324 else if (type == GL_HALF_FLOAT_OES)
1325 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001326 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001328 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001329 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 }
1331 }
1332 }
1333
Geoff Langdbcced82017-06-06 15:55:54 -04001334 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1335 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001336 imageSize))
1337 {
1338 return false;
1339 }
1340
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 return true;
1342}
1343
He Yunchaoced53ae2016-11-29 15:00:51 +08001344bool ValidateES2TexStorageParameters(Context *context,
1345 GLenum target,
1346 GLsizei levels,
1347 GLenum internalformat,
1348 GLsizei width,
1349 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350{
1351 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001353 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001354 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 }
1356
1357 if (width < 1 || height < 1 || levels < 1)
1358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
1362
1363 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001365 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 }
1368
1369 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 }
1374
Geoff Langca271392017-04-05 12:30:00 -04001375 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001376 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001379 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 }
1381
Geoff Langaae65a42014-05-26 12:43:44 -04001382 const gl::Caps &caps = context->getCaps();
1383
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 switch (target)
1385 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001386 case GL_TEXTURE_2D:
1387 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1388 static_cast<GLuint>(height) > caps.max2DTextureSize)
1389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001391 return false;
1392 }
1393 break;
1394 case GL_TEXTURE_CUBE_MAP:
1395 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1396 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001398 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001399 return false;
1400 }
1401 break;
1402 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001404 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405 }
1406
Geoff Langc0b9ef42014-07-02 10:02:37 -04001407 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 {
1409 if (!gl::isPow2(width) || !gl::isPow2(height))
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001412 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 }
1414 }
1415
1416 switch (internalformat)
1417 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001418 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1419 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1420 if (!context->getExtensions().textureCompressionDXT1)
1421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001422 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001423 return false;
1424 }
1425 break;
1426 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1427 if (!context->getExtensions().textureCompressionDXT3)
1428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001429 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001430 return false;
1431 }
1432 break;
1433 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1434 if (!context->getExtensions().textureCompressionDXT5)
1435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001437 return false;
1438 }
1439 break;
1440 case GL_ETC1_RGB8_OES:
1441 if (!context->getExtensions().compressedETC1RGB8Texture)
1442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001443 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 return false;
1445 }
1446 break;
1447 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001448 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1449 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1450 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1451 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001452 if (!context->getExtensions().lossyETCDecode)
1453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001454 context->handleError(InvalidEnum()
1455 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001456 return false;
1457 }
1458 break;
1459 case GL_RGBA32F_EXT:
1460 case GL_RGB32F_EXT:
1461 case GL_ALPHA32F_EXT:
1462 case GL_LUMINANCE32F_EXT:
1463 case GL_LUMINANCE_ALPHA32F_EXT:
1464 if (!context->getExtensions().textureFloat)
1465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001466 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001467 return false;
1468 }
1469 break;
1470 case GL_RGBA16F_EXT:
1471 case GL_RGB16F_EXT:
1472 case GL_ALPHA16F_EXT:
1473 case GL_LUMINANCE16F_EXT:
1474 case GL_LUMINANCE_ALPHA16F_EXT:
1475 if (!context->getExtensions().textureHalfFloat)
1476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 return false;
1479 }
1480 break;
1481 case GL_R8_EXT:
1482 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001483 if (!context->getExtensions().textureRG)
1484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001485 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001486 return false;
1487 }
1488 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001489 case GL_R16F_EXT:
1490 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001491 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001493 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001494 return false;
1495 }
1496 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001497 case GL_R32F_EXT:
1498 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001499 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001501 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001502 return false;
1503 }
1504 break;
1505 case GL_DEPTH_COMPONENT16:
1506 case GL_DEPTH_COMPONENT32_OES:
1507 case GL_DEPTH24_STENCIL8_OES:
1508 if (!context->getExtensions().depthTextures)
1509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001511 return false;
1512 }
1513 if (target != GL_TEXTURE_2D)
1514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001515 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001516 return false;
1517 }
1518 // ANGLE_depth_texture only supports 1-level textures
1519 if (levels != 1)
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001522 return false;
1523 }
1524 break;
1525 default:
1526 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001527 }
1528
Geoff Lang691e58c2014-12-19 17:03:25 -05001529 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001530 if (!texture || texture->id() == 0)
1531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001532 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001533 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 }
1535
Geoff Lang69cce582015-09-17 13:20:36 -04001536 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001538 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001539 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001540 }
1541
1542 return true;
1543}
1544
He Yunchaoced53ae2016-11-29 15:00:51 +08001545bool ValidateDiscardFramebufferEXT(Context *context,
1546 GLenum target,
1547 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001548 const GLenum *attachments)
1549{
Jamie Madillc29968b2016-01-20 11:17:23 -05001550 if (!context->getExtensions().discardFramebuffer)
1551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001552 context->handleError(InvalidOperation() << "Extension not enabled");
Jamie Madillc29968b2016-01-20 11:17:23 -05001553 return false;
1554 }
1555
Austin Kinross08332632015-05-05 13:35:47 -07001556 bool defaultFramebuffer = false;
1557
1558 switch (target)
1559 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001560 case GL_FRAMEBUFFER:
1561 defaultFramebuffer =
1562 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1563 break;
1564 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001565 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001566 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001567 }
1568
He Yunchaoced53ae2016-11-29 15:00:51 +08001569 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1570 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001571}
1572
Austin Kinrossbc781f32015-10-26 09:27:38 -07001573bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1574{
1575 if (!context->getExtensions().vertexArrayObject)
1576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001577 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001578 return false;
1579 }
1580
1581 return ValidateBindVertexArrayBase(context, array);
1582}
1583
1584bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1585{
1586 if (!context->getExtensions().vertexArrayObject)
1587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001588 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001589 return false;
1590 }
1591
Olli Etuaho41997e72016-03-10 13:38:39 +02001592 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001593}
1594
1595bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1596{
1597 if (!context->getExtensions().vertexArrayObject)
1598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001599 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001600 return false;
1601 }
1602
Olli Etuaho41997e72016-03-10 13:38:39 +02001603 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001604}
1605
1606bool ValidateIsVertexArrayOES(Context *context)
1607{
1608 if (!context->getExtensions().vertexArrayObject)
1609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001611 return false;
1612 }
1613
1614 return true;
1615}
Geoff Langc5629752015-12-07 16:29:04 -05001616
1617bool ValidateProgramBinaryOES(Context *context,
1618 GLuint program,
1619 GLenum binaryFormat,
1620 const void *binary,
1621 GLint length)
1622{
1623 if (!context->getExtensions().getProgramBinary)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001626 return false;
1627 }
1628
1629 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1630}
1631
1632bool ValidateGetProgramBinaryOES(Context *context,
1633 GLuint program,
1634 GLsizei bufSize,
1635 GLsizei *length,
1636 GLenum *binaryFormat,
1637 void *binary)
1638{
1639 if (!context->getExtensions().getProgramBinary)
1640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001642 return false;
1643 }
1644
1645 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1646}
Geoff Lange102fee2015-12-10 11:23:30 -05001647
Geoff Lang70d0f492015-12-10 17:45:46 -05001648static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1649{
1650 switch (source)
1651 {
1652 case GL_DEBUG_SOURCE_API:
1653 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1654 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1655 case GL_DEBUG_SOURCE_OTHER:
1656 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1657 return !mustBeThirdPartyOrApplication;
1658
1659 case GL_DEBUG_SOURCE_THIRD_PARTY:
1660 case GL_DEBUG_SOURCE_APPLICATION:
1661 return true;
1662
1663 default:
1664 return false;
1665 }
1666}
1667
1668static bool ValidDebugType(GLenum type)
1669{
1670 switch (type)
1671 {
1672 case GL_DEBUG_TYPE_ERROR:
1673 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1674 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1675 case GL_DEBUG_TYPE_PERFORMANCE:
1676 case GL_DEBUG_TYPE_PORTABILITY:
1677 case GL_DEBUG_TYPE_OTHER:
1678 case GL_DEBUG_TYPE_MARKER:
1679 case GL_DEBUG_TYPE_PUSH_GROUP:
1680 case GL_DEBUG_TYPE_POP_GROUP:
1681 return true;
1682
1683 default:
1684 return false;
1685 }
1686}
1687
1688static bool ValidDebugSeverity(GLenum severity)
1689{
1690 switch (severity)
1691 {
1692 case GL_DEBUG_SEVERITY_HIGH:
1693 case GL_DEBUG_SEVERITY_MEDIUM:
1694 case GL_DEBUG_SEVERITY_LOW:
1695 case GL_DEBUG_SEVERITY_NOTIFICATION:
1696 return true;
1697
1698 default:
1699 return false;
1700 }
1701}
1702
Geoff Lange102fee2015-12-10 11:23:30 -05001703bool ValidateDebugMessageControlKHR(Context *context,
1704 GLenum source,
1705 GLenum type,
1706 GLenum severity,
1707 GLsizei count,
1708 const GLuint *ids,
1709 GLboolean enabled)
1710{
1711 if (!context->getExtensions().debug)
1712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001713 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001714 return false;
1715 }
1716
Geoff Lang70d0f492015-12-10 17:45:46 -05001717 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001719 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001720 return false;
1721 }
1722
1723 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001725 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001726 return false;
1727 }
1728
1729 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001731 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001732 return false;
1733 }
1734
1735 if (count > 0)
1736 {
1737 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001739 context->handleError(
1740 InvalidOperation()
1741 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001742 return false;
1743 }
1744
1745 if (severity != GL_DONT_CARE)
1746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 InvalidOperation()
1749 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001750 return false;
1751 }
1752 }
1753
Geoff Lange102fee2015-12-10 11:23:30 -05001754 return true;
1755}
1756
1757bool ValidateDebugMessageInsertKHR(Context *context,
1758 GLenum source,
1759 GLenum type,
1760 GLuint id,
1761 GLenum severity,
1762 GLsizei length,
1763 const GLchar *buf)
1764{
1765 if (!context->getExtensions().debug)
1766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001767 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001768 return false;
1769 }
1770
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001771 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001772 {
1773 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1774 // not generate an error.
1775 return false;
1776 }
1777
1778 if (!ValidDebugSeverity(severity))
1779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001781 return false;
1782 }
1783
1784 if (!ValidDebugType(type))
1785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001786 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001787 return false;
1788 }
1789
1790 if (!ValidDebugSource(source, true))
1791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001792 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001793 return false;
1794 }
1795
1796 size_t messageLength = (length < 0) ? strlen(buf) : length;
1797 if (messageLength > context->getExtensions().maxDebugMessageLength)
1798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(InvalidValue()
1800 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001801 return false;
1802 }
1803
Geoff Lange102fee2015-12-10 11:23:30 -05001804 return true;
1805}
1806
1807bool ValidateDebugMessageCallbackKHR(Context *context,
1808 GLDEBUGPROCKHR callback,
1809 const void *userParam)
1810{
1811 if (!context->getExtensions().debug)
1812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001813 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001814 return false;
1815 }
1816
Geoff Lange102fee2015-12-10 11:23:30 -05001817 return true;
1818}
1819
1820bool ValidateGetDebugMessageLogKHR(Context *context,
1821 GLuint count,
1822 GLsizei bufSize,
1823 GLenum *sources,
1824 GLenum *types,
1825 GLuint *ids,
1826 GLenum *severities,
1827 GLsizei *lengths,
1828 GLchar *messageLog)
1829{
1830 if (!context->getExtensions().debug)
1831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001832 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001833 return false;
1834 }
1835
Geoff Lang70d0f492015-12-10 17:45:46 -05001836 if (bufSize < 0 && messageLog != nullptr)
1837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001838 context->handleError(InvalidValue()
1839 << "bufSize must be positive if messageLog is not null.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001840 return false;
1841 }
1842
Geoff Lange102fee2015-12-10 11:23:30 -05001843 return true;
1844}
1845
1846bool ValidatePushDebugGroupKHR(Context *context,
1847 GLenum source,
1848 GLuint id,
1849 GLsizei length,
1850 const GLchar *message)
1851{
1852 if (!context->getExtensions().debug)
1853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001854 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001855 return false;
1856 }
1857
Geoff Lang70d0f492015-12-10 17:45:46 -05001858 if (!ValidDebugSource(source, true))
1859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001860 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001861 return false;
1862 }
1863
1864 size_t messageLength = (length < 0) ? strlen(message) : length;
1865 if (messageLength > context->getExtensions().maxDebugMessageLength)
1866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001867 context->handleError(InvalidValue()
1868 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001869 return false;
1870 }
1871
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001872 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001873 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001875 context
1876 ->handleError(StackOverflow()
1877 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001878 return false;
1879 }
1880
Geoff Lange102fee2015-12-10 11:23:30 -05001881 return true;
1882}
1883
1884bool ValidatePopDebugGroupKHR(Context *context)
1885{
1886 if (!context->getExtensions().debug)
1887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001888 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001889 return false;
1890 }
1891
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001892 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001893 if (currentStackSize <= 1)
1894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001895 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001896 return false;
1897 }
1898
1899 return true;
1900}
1901
1902static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1903{
1904 switch (identifier)
1905 {
1906 case GL_BUFFER:
1907 if (context->getBuffer(name) == nullptr)
1908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001909 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001910 return false;
1911 }
1912 return true;
1913
1914 case GL_SHADER:
1915 if (context->getShader(name) == nullptr)
1916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001917 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001918 return false;
1919 }
1920 return true;
1921
1922 case GL_PROGRAM:
1923 if (context->getProgram(name) == nullptr)
1924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001925 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001926 return false;
1927 }
1928 return true;
1929
1930 case GL_VERTEX_ARRAY:
1931 if (context->getVertexArray(name) == nullptr)
1932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001933 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001934 return false;
1935 }
1936 return true;
1937
1938 case GL_QUERY:
1939 if (context->getQuery(name) == nullptr)
1940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001941 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001942 return false;
1943 }
1944 return true;
1945
1946 case GL_TRANSFORM_FEEDBACK:
1947 if (context->getTransformFeedback(name) == nullptr)
1948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001949 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001950 return false;
1951 }
1952 return true;
1953
1954 case GL_SAMPLER:
1955 if (context->getSampler(name) == nullptr)
1956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001957 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001958 return false;
1959 }
1960 return true;
1961
1962 case GL_TEXTURE:
1963 if (context->getTexture(name) == nullptr)
1964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001966 return false;
1967 }
1968 return true;
1969
1970 case GL_RENDERBUFFER:
1971 if (context->getRenderbuffer(name) == nullptr)
1972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001973 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001974 return false;
1975 }
1976 return true;
1977
1978 case GL_FRAMEBUFFER:
1979 if (context->getFramebuffer(name) == nullptr)
1980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001981 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001982 return false;
1983 }
1984 return true;
1985
1986 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001987 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001988 return false;
1989 }
Geoff Lange102fee2015-12-10 11:23:30 -05001990}
1991
Martin Radev9d901792016-07-15 15:58:58 +03001992static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1993{
1994 size_t labelLength = 0;
1995
1996 if (length < 0)
1997 {
1998 if (label != nullptr)
1999 {
2000 labelLength = strlen(label);
2001 }
2002 }
2003 else
2004 {
2005 labelLength = static_cast<size_t>(length);
2006 }
2007
2008 if (labelLength > context->getExtensions().maxLabelLength)
2009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002010 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002011 return false;
2012 }
2013
2014 return true;
2015}
2016
Geoff Lange102fee2015-12-10 11:23:30 -05002017bool ValidateObjectLabelKHR(Context *context,
2018 GLenum identifier,
2019 GLuint name,
2020 GLsizei length,
2021 const GLchar *label)
2022{
2023 if (!context->getExtensions().debug)
2024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002025 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002026 return false;
2027 }
2028
Geoff Lang70d0f492015-12-10 17:45:46 -05002029 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2030 {
2031 return false;
2032 }
2033
Martin Radev9d901792016-07-15 15:58:58 +03002034 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002035 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002036 return false;
2037 }
2038
Geoff Lange102fee2015-12-10 11:23:30 -05002039 return true;
2040}
2041
2042bool ValidateGetObjectLabelKHR(Context *context,
2043 GLenum identifier,
2044 GLuint name,
2045 GLsizei bufSize,
2046 GLsizei *length,
2047 GLchar *label)
2048{
2049 if (!context->getExtensions().debug)
2050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002051 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002052 return false;
2053 }
2054
Geoff Lang70d0f492015-12-10 17:45:46 -05002055 if (bufSize < 0)
2056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002057 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002058 return false;
2059 }
2060
2061 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2062 {
2063 return false;
2064 }
2065
Martin Radev9d901792016-07-15 15:58:58 +03002066 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002067}
2068
2069static bool ValidateObjectPtrName(Context *context, const void *ptr)
2070{
2071 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002073 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002074 return false;
2075 }
2076
Geoff Lange102fee2015-12-10 11:23:30 -05002077 return true;
2078}
2079
2080bool ValidateObjectPtrLabelKHR(Context *context,
2081 const void *ptr,
2082 GLsizei length,
2083 const GLchar *label)
2084{
2085 if (!context->getExtensions().debug)
2086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002087 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002088 return false;
2089 }
2090
Geoff Lang70d0f492015-12-10 17:45:46 -05002091 if (!ValidateObjectPtrName(context, ptr))
2092 {
2093 return false;
2094 }
2095
Martin Radev9d901792016-07-15 15:58:58 +03002096 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002097 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002098 return false;
2099 }
2100
Geoff Lange102fee2015-12-10 11:23:30 -05002101 return true;
2102}
2103
2104bool ValidateGetObjectPtrLabelKHR(Context *context,
2105 const void *ptr,
2106 GLsizei bufSize,
2107 GLsizei *length,
2108 GLchar *label)
2109{
2110 if (!context->getExtensions().debug)
2111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002112 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002113 return false;
2114 }
2115
Geoff Lang70d0f492015-12-10 17:45:46 -05002116 if (bufSize < 0)
2117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002118 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002119 return false;
2120 }
2121
2122 if (!ValidateObjectPtrName(context, ptr))
2123 {
2124 return false;
2125 }
2126
Martin Radev9d901792016-07-15 15:58:58 +03002127 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002128}
2129
2130bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2131{
2132 if (!context->getExtensions().debug)
2133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002134 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002135 return false;
2136 }
2137
Geoff Lang70d0f492015-12-10 17:45:46 -05002138 // TODO: represent this in Context::getQueryParameterInfo.
2139 switch (pname)
2140 {
2141 case GL_DEBUG_CALLBACK_FUNCTION:
2142 case GL_DEBUG_CALLBACK_USER_PARAM:
2143 break;
2144
2145 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002146 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002147 return false;
2148 }
2149
Geoff Lange102fee2015-12-10 11:23:30 -05002150 return true;
2151}
Jamie Madillc29968b2016-01-20 11:17:23 -05002152
2153bool ValidateBlitFramebufferANGLE(Context *context,
2154 GLint srcX0,
2155 GLint srcY0,
2156 GLint srcX1,
2157 GLint srcY1,
2158 GLint dstX0,
2159 GLint dstY0,
2160 GLint dstX1,
2161 GLint dstY1,
2162 GLbitfield mask,
2163 GLenum filter)
2164{
2165 if (!context->getExtensions().framebufferBlit)
2166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002167 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002168 return false;
2169 }
2170
2171 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2172 {
2173 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002174 context->handleError(InvalidOperation() << "Scaling and flipping in "
2175 "BlitFramebufferANGLE not supported by this "
2176 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002177 return false;
2178 }
2179
2180 if (filter == GL_LINEAR)
2181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002182 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002183 return false;
2184 }
2185
Jamie Madill51f40ec2016-06-15 14:06:00 -04002186 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2187 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002188
2189 if (mask & GL_COLOR_BUFFER_BIT)
2190 {
2191 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2192 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2193
2194 if (readColorAttachment && drawColorAttachment)
2195 {
2196 if (!(readColorAttachment->type() == GL_TEXTURE &&
2197 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2198 readColorAttachment->type() != GL_RENDERBUFFER &&
2199 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002201 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002202 return false;
2203 }
2204
Geoff Langa15472a2015-08-11 11:48:03 -04002205 for (size_t drawbufferIdx = 0;
2206 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002207 {
Geoff Langa15472a2015-08-11 11:48:03 -04002208 const FramebufferAttachment *attachment =
2209 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2210 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002211 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002212 if (!(attachment->type() == GL_TEXTURE &&
2213 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2214 attachment->type() != GL_RENDERBUFFER &&
2215 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002217 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002218 return false;
2219 }
2220
2221 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002222 if (!Format::SameSized(attachment->getFormat(),
2223 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002225 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002226 return false;
2227 }
2228 }
2229 }
2230
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002231 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002232 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2233 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002235 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002236 return false;
2237 }
2238 }
2239 }
2240
2241 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2242 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2243 for (size_t i = 0; i < 2; i++)
2244 {
2245 if (mask & masks[i])
2246 {
2247 const FramebufferAttachment *readBuffer =
2248 readFramebuffer->getAttachment(attachments[i]);
2249 const FramebufferAttachment *drawBuffer =
2250 drawFramebuffer->getAttachment(attachments[i]);
2251
2252 if (readBuffer && drawBuffer)
2253 {
2254 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2255 dstX0, dstY0, dstX1, dstY1))
2256 {
2257 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002258 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2259 "stencil blits are supported by "
2260 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002261 return false;
2262 }
2263
2264 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002266 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002267 return false;
2268 }
2269 }
2270 }
2271 }
2272
2273 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2274 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002275}
Jamie Madillc29968b2016-01-20 11:17:23 -05002276
2277bool ValidateClear(ValidationContext *context, GLbitfield mask)
2278{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002279 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002280 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002282 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002283 return false;
2284 }
2285
2286 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002288 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05002289 return false;
2290 }
2291
Geoff Lang76e65652017-03-27 14:58:02 -04002292 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2293 {
2294 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2295 GL_SIGNED_NORMALIZED};
2296
2297 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2298 drawBufferIdx++)
2299 {
2300 if (!ValidateWebGLFramebufferAttachmentClearType(
2301 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2302 {
2303 return false;
2304 }
2305 }
2306 }
2307
Jamie Madillc29968b2016-01-20 11:17:23 -05002308 return true;
2309}
2310
2311bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2312{
2313 if (!context->getExtensions().drawBuffers)
2314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002315 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002316 return false;
2317 }
2318
2319 return ValidateDrawBuffersBase(context, n, bufs);
2320}
2321
Jamie Madill73a84962016-02-12 09:27:23 -05002322bool ValidateTexImage2D(Context *context,
2323 GLenum target,
2324 GLint level,
2325 GLint internalformat,
2326 GLsizei width,
2327 GLsizei height,
2328 GLint border,
2329 GLenum format,
2330 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002331 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002332{
Martin Radev1be913c2016-07-11 17:59:16 +03002333 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002334 {
2335 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002336 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002337 }
2338
Martin Radev1be913c2016-07-11 17:59:16 +03002339 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002340 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002341 0, 0, width, height, 1, border, format, type, -1,
2342 pixels);
2343}
2344
2345bool ValidateTexImage2DRobust(Context *context,
2346 GLenum target,
2347 GLint level,
2348 GLint internalformat,
2349 GLsizei width,
2350 GLsizei height,
2351 GLint border,
2352 GLenum format,
2353 GLenum type,
2354 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002355 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002356{
2357 if (!ValidateRobustEntryPoint(context, bufSize))
2358 {
2359 return false;
2360 }
2361
2362 if (context->getClientMajorVersion() < 3)
2363 {
2364 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2365 0, 0, width, height, border, format, type, bufSize,
2366 pixels);
2367 }
2368
2369 ASSERT(context->getClientMajorVersion() >= 3);
2370 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2371 0, 0, width, height, 1, border, format, type, bufSize,
2372 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002373}
2374
2375bool ValidateTexSubImage2D(Context *context,
2376 GLenum target,
2377 GLint level,
2378 GLint xoffset,
2379 GLint yoffset,
2380 GLsizei width,
2381 GLsizei height,
2382 GLenum format,
2383 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002384 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002385{
2386
Martin Radev1be913c2016-07-11 17:59:16 +03002387 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002388 {
2389 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002390 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002391 }
2392
Martin Radev1be913c2016-07-11 17:59:16 +03002393 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002394 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002395 yoffset, 0, width, height, 1, 0, format, type, -1,
2396 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002397}
2398
Geoff Langc52f6f12016-10-14 10:18:00 -04002399bool ValidateTexSubImage2DRobustANGLE(Context *context,
2400 GLenum target,
2401 GLint level,
2402 GLint xoffset,
2403 GLint yoffset,
2404 GLsizei width,
2405 GLsizei height,
2406 GLenum format,
2407 GLenum type,
2408 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002409 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002410{
2411 if (!ValidateRobustEntryPoint(context, bufSize))
2412 {
2413 return false;
2414 }
2415
2416 if (context->getClientMajorVersion() < 3)
2417 {
2418 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2419 yoffset, width, height, 0, format, type, bufSize,
2420 pixels);
2421 }
2422
2423 ASSERT(context->getClientMajorVersion() >= 3);
2424 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2425 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2426 pixels);
2427}
2428
Jamie Madill73a84962016-02-12 09:27:23 -05002429bool ValidateCompressedTexImage2D(Context *context,
2430 GLenum target,
2431 GLint level,
2432 GLenum internalformat,
2433 GLsizei width,
2434 GLsizei height,
2435 GLint border,
2436 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002437 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002438{
Martin Radev1be913c2016-07-11 17:59:16 +03002439 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002440 {
2441 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002442 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002443 {
2444 return false;
2445 }
2446 }
2447 else
2448 {
Martin Radev1be913c2016-07-11 17:59:16 +03002449 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002450 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002451 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002452 data))
2453 {
2454 return false;
2455 }
2456 }
2457
Geoff Langca271392017-04-05 12:30:00 -04002458 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002459 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002460 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002461 if (blockSizeOrErr.isError())
2462 {
2463 context->handleError(blockSizeOrErr.getError());
2464 return false;
2465 }
2466
2467 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002469 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002470 return false;
2471 }
2472
2473 return true;
2474}
2475
Corentin Wallezb2931602017-04-11 15:58:57 -04002476bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2477 GLenum target,
2478 GLint level,
2479 GLenum internalformat,
2480 GLsizei width,
2481 GLsizei height,
2482 GLint border,
2483 GLsizei imageSize,
2484 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002485 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002486{
2487 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2488 {
2489 return false;
2490 }
2491
2492 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2493 border, imageSize, data);
2494}
2495bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2496 GLenum target,
2497 GLint level,
2498 GLint xoffset,
2499 GLint yoffset,
2500 GLsizei width,
2501 GLsizei height,
2502 GLenum format,
2503 GLsizei imageSize,
2504 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002505 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002506{
2507 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2508 {
2509 return false;
2510 }
2511
2512 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2513 format, imageSize, data);
2514}
2515
Jamie Madill73a84962016-02-12 09:27:23 -05002516bool ValidateCompressedTexSubImage2D(Context *context,
2517 GLenum target,
2518 GLint level,
2519 GLint xoffset,
2520 GLint yoffset,
2521 GLsizei width,
2522 GLsizei height,
2523 GLenum format,
2524 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002525 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002526{
Martin Radev1be913c2016-07-11 17:59:16 +03002527 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002528 {
2529 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002530 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002531 {
2532 return false;
2533 }
2534 }
2535 else
2536 {
Martin Radev1be913c2016-07-11 17:59:16 +03002537 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002538 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002539 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002540 data))
2541 {
2542 return false;
2543 }
2544 }
2545
Geoff Langca271392017-04-05 12:30:00 -04002546 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002547 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002548 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002549 if (blockSizeOrErr.isError())
2550 {
2551 context->handleError(blockSizeOrErr.getError());
2552 return false;
2553 }
2554
2555 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002557 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002558 return false;
2559 }
2560
2561 return true;
2562}
2563
Olli Etuaho4f667482016-03-30 15:56:35 +03002564bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2565{
Geoff Lang496c02d2016-10-20 11:38:11 -07002566 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002567}
2568
2569bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2570{
2571 if (!context->getExtensions().mapBuffer)
2572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002573 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002574 return false;
2575 }
2576
2577 if (!ValidBufferTarget(context, target))
2578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002579 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002580 return false;
2581 }
2582
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002583 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002584
2585 if (buffer == nullptr)
2586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002587 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002588 return false;
2589 }
2590
2591 if (access != GL_WRITE_ONLY_OES)
2592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002593 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002594 return false;
2595 }
2596
2597 if (buffer->isMapped())
2598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002599 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002600 return false;
2601 }
2602
2603 return true;
2604}
2605
2606bool ValidateUnmapBufferOES(Context *context, GLenum target)
2607{
2608 if (!context->getExtensions().mapBuffer)
2609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002610 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002611 return false;
2612 }
2613
2614 return ValidateUnmapBufferBase(context, target);
2615}
2616
2617bool ValidateMapBufferRangeEXT(Context *context,
2618 GLenum target,
2619 GLintptr offset,
2620 GLsizeiptr length,
2621 GLbitfield access)
2622{
2623 if (!context->getExtensions().mapBufferRange)
2624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002625 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002626 return false;
2627 }
2628
2629 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2630}
2631
2632bool ValidateFlushMappedBufferRangeEXT(Context *context,
2633 GLenum target,
2634 GLintptr offset,
2635 GLsizeiptr length)
2636{
2637 if (!context->getExtensions().mapBufferRange)
2638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002639 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002640 return false;
2641 }
2642
2643 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2644}
2645
Ian Ewell54f87462016-03-10 13:47:21 -05002646bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2647{
2648 Texture *textureObject = context->getTexture(texture);
2649 if (textureObject && textureObject->getTarget() != target && texture != 0)
2650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002651 context->handleError(InvalidOperation() << "Invalid texture");
Ian Ewell54f87462016-03-10 13:47:21 -05002652 return false;
2653 }
2654
Geoff Langf41a7152016-09-19 15:11:17 -04002655 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2656 !context->isTextureGenerated(texture))
2657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002658 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002659 return false;
2660 }
2661
Ian Ewell54f87462016-03-10 13:47:21 -05002662 switch (target)
2663 {
2664 case GL_TEXTURE_2D:
2665 case GL_TEXTURE_CUBE_MAP:
2666 break;
2667
2668 case GL_TEXTURE_3D:
2669 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002670 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002672 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002673 return false;
2674 }
2675 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002676
2677 case GL_TEXTURE_2D_MULTISAMPLE:
2678 if (context->getClientVersion() < Version(3, 1))
2679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002680 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002681 return false;
2682 }
Geoff Lang3b573612016-10-31 14:08:10 -04002683 break;
2684
Ian Ewell54f87462016-03-10 13:47:21 -05002685 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002686 if (!context->getExtensions().eglImageExternal &&
2687 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002689 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002690 return false;
2691 }
2692 break;
2693 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002694 context->handleError(InvalidEnum() << "Invalid target");
Ian Ewell54f87462016-03-10 13:47:21 -05002695 return false;
2696 }
2697
2698 return true;
2699}
2700
Geoff Langd8605522016-04-13 10:19:12 -04002701bool ValidateBindUniformLocationCHROMIUM(Context *context,
2702 GLuint program,
2703 GLint location,
2704 const GLchar *name)
2705{
2706 if (!context->getExtensions().bindUniformLocation)
2707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002708 context->handleError(InvalidOperation()
2709 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002710 return false;
2711 }
2712
2713 Program *programObject = GetValidProgram(context, program);
2714 if (!programObject)
2715 {
2716 return false;
2717 }
2718
2719 if (location < 0)
2720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002721 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002722 return false;
2723 }
2724
2725 const Caps &caps = context->getCaps();
2726 if (static_cast<size_t>(location) >=
2727 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002729 context->handleError(InvalidValue() << "Location must be less than "
2730 "(MAX_VERTEX_UNIFORM_VECTORS + "
2731 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002732 return false;
2733 }
2734
Geoff Langfc32e8b2017-05-31 14:16:59 -04002735 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2736 // shader-related entry points
2737 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
2738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002739 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04002740 return false;
2741 }
2742
Geoff Langd8605522016-04-13 10:19:12 -04002743 if (strncmp(name, "gl_", 3) == 0)
2744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002745 context->handleError(InvalidOperation()
2746 << "Name cannot start with the reserved \"gl_\" prefix.");
Geoff Langd8605522016-04-13 10:19:12 -04002747 return false;
2748 }
2749
2750 return true;
2751}
2752
Jamie Madille2e406c2016-06-02 13:04:10 -04002753bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002754{
2755 if (!context->getExtensions().framebufferMixedSamples)
2756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002757 context->handleError(InvalidOperation()
2758 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002759 return false;
2760 }
2761 switch (components)
2762 {
2763 case GL_RGB:
2764 case GL_RGBA:
2765 case GL_ALPHA:
2766 case GL_NONE:
2767 break;
2768 default:
2769 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002770 InvalidEnum()
2771 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002772 return false;
2773 }
2774
2775 return true;
2776}
2777
Sami Väisänene45e53b2016-05-25 10:36:04 +03002778// CHROMIUM_path_rendering
2779
2780bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2781{
2782 if (!context->getExtensions().pathRendering)
2783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002784 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002785 return false;
2786 }
2787 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002789 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002790 return false;
2791 }
2792 if (matrix == nullptr)
2793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002794 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002795 return false;
2796 }
2797 return true;
2798}
2799
2800bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2801{
2802 if (!context->getExtensions().pathRendering)
2803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002804 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002805 return false;
2806 }
2807 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002809 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002810 return false;
2811 }
2812 return true;
2813}
2814
2815bool ValidateGenPaths(Context *context, GLsizei range)
2816{
2817 if (!context->getExtensions().pathRendering)
2818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002819 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002820 return false;
2821 }
2822
2823 // range = 0 is undefined in NV_path_rendering.
2824 // we add stricter semantic check here and require a non zero positive range.
2825 if (range <= 0)
2826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002827 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002828 return false;
2829 }
2830
2831 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002833 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002834 return false;
2835 }
2836
2837 return true;
2838}
2839
2840bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2841{
2842 if (!context->getExtensions().pathRendering)
2843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002844 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002845 return false;
2846 }
2847
2848 // range = 0 is undefined in NV_path_rendering.
2849 // we add stricter semantic check here and require a non zero positive range.
2850 if (range <= 0)
2851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002852 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002853 return false;
2854 }
2855
2856 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2857 checkedRange += range;
2858
2859 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002861 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002862 return false;
2863 }
2864 return true;
2865}
2866
2867bool ValidatePathCommands(Context *context,
2868 GLuint path,
2869 GLsizei numCommands,
2870 const GLubyte *commands,
2871 GLsizei numCoords,
2872 GLenum coordType,
2873 const void *coords)
2874{
2875 if (!context->getExtensions().pathRendering)
2876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002877 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002878 return false;
2879 }
2880 if (!context->hasPath(path))
2881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002882 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002883 return false;
2884 }
2885
2886 if (numCommands < 0)
2887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002888 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002889 return false;
2890 }
2891 else if (numCommands > 0)
2892 {
2893 if (!commands)
2894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002895 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002896 return false;
2897 }
2898 }
2899
2900 if (numCoords < 0)
2901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002902 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002903 return false;
2904 }
2905 else if (numCoords > 0)
2906 {
2907 if (!coords)
2908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002909 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002910 return false;
2911 }
2912 }
2913
2914 std::uint32_t coordTypeSize = 0;
2915 switch (coordType)
2916 {
2917 case GL_BYTE:
2918 coordTypeSize = sizeof(GLbyte);
2919 break;
2920
2921 case GL_UNSIGNED_BYTE:
2922 coordTypeSize = sizeof(GLubyte);
2923 break;
2924
2925 case GL_SHORT:
2926 coordTypeSize = sizeof(GLshort);
2927 break;
2928
2929 case GL_UNSIGNED_SHORT:
2930 coordTypeSize = sizeof(GLushort);
2931 break;
2932
2933 case GL_FLOAT:
2934 coordTypeSize = sizeof(GLfloat);
2935 break;
2936
2937 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002938 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002939 return false;
2940 }
2941
2942 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2943 checkedSize += (coordTypeSize * numCoords);
2944 if (!checkedSize.IsValid())
2945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002946 context->handleError(InvalidOperation() << "Coord size overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002947 return false;
2948 }
2949
2950 // early return skips command data validation when it doesn't exist.
2951 if (!commands)
2952 return true;
2953
2954 GLsizei expectedNumCoords = 0;
2955 for (GLsizei i = 0; i < numCommands; ++i)
2956 {
2957 switch (commands[i])
2958 {
2959 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2960 break;
2961 case GL_MOVE_TO_CHROMIUM:
2962 case GL_LINE_TO_CHROMIUM:
2963 expectedNumCoords += 2;
2964 break;
2965 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2966 expectedNumCoords += 4;
2967 break;
2968 case GL_CUBIC_CURVE_TO_CHROMIUM:
2969 expectedNumCoords += 6;
2970 break;
2971 case GL_CONIC_CURVE_TO_CHROMIUM:
2972 expectedNumCoords += 5;
2973 break;
2974 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002975 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002976 return false;
2977 }
2978 }
2979 if (expectedNumCoords != numCoords)
2980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002981 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002982 return false;
2983 }
2984
2985 return true;
2986}
2987
2988bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2989{
2990 if (!context->getExtensions().pathRendering)
2991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002992 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002993 return false;
2994 }
2995 if (!context->hasPath(path))
2996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002997 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002998 return false;
2999 }
3000
3001 switch (pname)
3002 {
3003 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3004 if (value < 0.0f)
3005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003006 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003007 return false;
3008 }
3009 break;
3010 case GL_PATH_END_CAPS_CHROMIUM:
3011 switch (static_cast<GLenum>(value))
3012 {
3013 case GL_FLAT_CHROMIUM:
3014 case GL_SQUARE_CHROMIUM:
3015 case GL_ROUND_CHROMIUM:
3016 break;
3017 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003018 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003019 return false;
3020 }
3021 break;
3022 case GL_PATH_JOIN_STYLE_CHROMIUM:
3023 switch (static_cast<GLenum>(value))
3024 {
3025 case GL_MITER_REVERT_CHROMIUM:
3026 case GL_BEVEL_CHROMIUM:
3027 case GL_ROUND_CHROMIUM:
3028 break;
3029 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003030 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003031 return false;
3032 }
3033 case GL_PATH_MITER_LIMIT_CHROMIUM:
3034 if (value < 0.0f)
3035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003036 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003037 return false;
3038 }
3039 break;
3040
3041 case GL_PATH_STROKE_BOUND_CHROMIUM:
3042 // no errors, only clamping.
3043 break;
3044
3045 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003046 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003047 return false;
3048 }
3049 return true;
3050}
3051
3052bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3053{
3054 if (!context->getExtensions().pathRendering)
3055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003056 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003057 return false;
3058 }
3059
3060 if (!context->hasPath(path))
3061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003062 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003063 return false;
3064 }
3065 if (!value)
3066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003067 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003068 return false;
3069 }
3070
3071 switch (pname)
3072 {
3073 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3074 case GL_PATH_END_CAPS_CHROMIUM:
3075 case GL_PATH_JOIN_STYLE_CHROMIUM:
3076 case GL_PATH_MITER_LIMIT_CHROMIUM:
3077 case GL_PATH_STROKE_BOUND_CHROMIUM:
3078 break;
3079
3080 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003081 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003082 return false;
3083 }
3084
3085 return true;
3086}
3087
3088bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3089{
3090 if (!context->getExtensions().pathRendering)
3091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003092 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003093 return false;
3094 }
3095
3096 switch (func)
3097 {
3098 case GL_NEVER:
3099 case GL_ALWAYS:
3100 case GL_LESS:
3101 case GL_LEQUAL:
3102 case GL_EQUAL:
3103 case GL_GEQUAL:
3104 case GL_GREATER:
3105 case GL_NOTEQUAL:
3106 break;
3107 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003108 context->handleError(InvalidEnum() << "Invalid stencil function.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003109 return false;
3110 }
3111
3112 return true;
3113}
3114
3115// Note that the spec specifies that for the path drawing commands
3116// if the path object is not an existing path object the command
3117// does nothing and no error is generated.
3118// However if the path object exists but has not been specified any
3119// commands then an error is generated.
3120
3121bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3122{
3123 if (!context->getExtensions().pathRendering)
3124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003125 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003126 return false;
3127 }
3128 if (context->hasPath(path) && !context->hasPathData(path))
3129 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003130 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003131 return false;
3132 }
3133
3134 switch (fillMode)
3135 {
3136 case GL_COUNT_UP_CHROMIUM:
3137 case GL_COUNT_DOWN_CHROMIUM:
3138 break;
3139 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003140 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003141 return false;
3142 }
3143
3144 if (!isPow2(mask + 1))
3145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003146 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003147 return false;
3148 }
3149
3150 return true;
3151}
3152
3153bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3154{
3155 if (!context->getExtensions().pathRendering)
3156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003157 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003158 return false;
3159 }
3160 if (context->hasPath(path) && !context->hasPathData(path))
3161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003162 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003163 return false;
3164 }
3165
3166 return true;
3167}
3168
3169bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3170{
3171 if (!context->getExtensions().pathRendering)
3172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003173 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003174 return false;
3175 }
3176 if (context->hasPath(path) && !context->hasPathData(path))
3177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003178 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003179 return false;
3180 }
3181
3182 switch (coverMode)
3183 {
3184 case GL_CONVEX_HULL_CHROMIUM:
3185 case GL_BOUNDING_BOX_CHROMIUM:
3186 break;
3187 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003188 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003189 return false;
3190 }
3191 return true;
3192}
3193
3194bool ValidateStencilThenCoverFillPath(Context *context,
3195 GLuint path,
3196 GLenum fillMode,
3197 GLuint mask,
3198 GLenum coverMode)
3199{
3200 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3201 ValidateCoverPath(context, path, coverMode);
3202}
3203
3204bool ValidateStencilThenCoverStrokePath(Context *context,
3205 GLuint path,
3206 GLint reference,
3207 GLuint mask,
3208 GLenum coverMode)
3209{
3210 return ValidateStencilStrokePath(context, path, reference, mask) &&
3211 ValidateCoverPath(context, path, coverMode);
3212}
3213
3214bool ValidateIsPath(Context *context)
3215{
3216 if (!context->getExtensions().pathRendering)
3217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003218 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003219 return false;
3220 }
3221 return true;
3222}
3223
Sami Väisänend59ca052016-06-21 16:10:00 +03003224bool ValidateCoverFillPathInstanced(Context *context,
3225 GLsizei numPaths,
3226 GLenum pathNameType,
3227 const void *paths,
3228 GLuint pathBase,
3229 GLenum coverMode,
3230 GLenum transformType,
3231 const GLfloat *transformValues)
3232{
3233 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3234 transformType, transformValues))
3235 return false;
3236
3237 switch (coverMode)
3238 {
3239 case GL_CONVEX_HULL_CHROMIUM:
3240 case GL_BOUNDING_BOX_CHROMIUM:
3241 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3242 break;
3243 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003244 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003245 return false;
3246 }
3247
3248 return true;
3249}
3250
3251bool ValidateCoverStrokePathInstanced(Context *context,
3252 GLsizei numPaths,
3253 GLenum pathNameType,
3254 const void *paths,
3255 GLuint pathBase,
3256 GLenum coverMode,
3257 GLenum transformType,
3258 const GLfloat *transformValues)
3259{
3260 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3261 transformType, transformValues))
3262 return false;
3263
3264 switch (coverMode)
3265 {
3266 case GL_CONVEX_HULL_CHROMIUM:
3267 case GL_BOUNDING_BOX_CHROMIUM:
3268 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3269 break;
3270 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003271 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003272 return false;
3273 }
3274
3275 return true;
3276}
3277
3278bool ValidateStencilFillPathInstanced(Context *context,
3279 GLsizei numPaths,
3280 GLenum pathNameType,
3281 const void *paths,
3282 GLuint pathBase,
3283 GLenum fillMode,
3284 GLuint mask,
3285 GLenum transformType,
3286 const GLfloat *transformValues)
3287{
3288
3289 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3290 transformType, transformValues))
3291 return false;
3292
3293 switch (fillMode)
3294 {
3295 case GL_COUNT_UP_CHROMIUM:
3296 case GL_COUNT_DOWN_CHROMIUM:
3297 break;
3298 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003299 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003300 return false;
3301 }
3302 if (!isPow2(mask + 1))
3303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003304 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003305 return false;
3306 }
3307 return true;
3308}
3309
3310bool ValidateStencilStrokePathInstanced(Context *context,
3311 GLsizei numPaths,
3312 GLenum pathNameType,
3313 const void *paths,
3314 GLuint pathBase,
3315 GLint reference,
3316 GLuint mask,
3317 GLenum transformType,
3318 const GLfloat *transformValues)
3319{
3320 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3321 transformType, transformValues))
3322 return false;
3323
3324 // no more validation here.
3325
3326 return true;
3327}
3328
3329bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3330 GLsizei numPaths,
3331 GLenum pathNameType,
3332 const void *paths,
3333 GLuint pathBase,
3334 GLenum fillMode,
3335 GLuint mask,
3336 GLenum coverMode,
3337 GLenum transformType,
3338 const GLfloat *transformValues)
3339{
3340 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3341 transformType, transformValues))
3342 return false;
3343
3344 switch (coverMode)
3345 {
3346 case GL_CONVEX_HULL_CHROMIUM:
3347 case GL_BOUNDING_BOX_CHROMIUM:
3348 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3349 break;
3350 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003351 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003352 return false;
3353 }
3354
3355 switch (fillMode)
3356 {
3357 case GL_COUNT_UP_CHROMIUM:
3358 case GL_COUNT_DOWN_CHROMIUM:
3359 break;
3360 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003361 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003362 return false;
3363 }
3364 if (!isPow2(mask + 1))
3365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003367 return false;
3368 }
3369
3370 return true;
3371}
3372
3373bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3374 GLsizei numPaths,
3375 GLenum pathNameType,
3376 const void *paths,
3377 GLuint pathBase,
3378 GLint reference,
3379 GLuint mask,
3380 GLenum coverMode,
3381 GLenum transformType,
3382 const GLfloat *transformValues)
3383{
3384 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3385 transformType, transformValues))
3386 return false;
3387
3388 switch (coverMode)
3389 {
3390 case GL_CONVEX_HULL_CHROMIUM:
3391 case GL_BOUNDING_BOX_CHROMIUM:
3392 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3393 break;
3394 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003395 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003396 return false;
3397 }
3398
3399 return true;
3400}
3401
Sami Väisänen46eaa942016-06-29 10:26:37 +03003402bool ValidateBindFragmentInputLocation(Context *context,
3403 GLuint program,
3404 GLint location,
3405 const GLchar *name)
3406{
3407 if (!context->getExtensions().pathRendering)
3408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003409 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003410 return false;
3411 }
3412
3413 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3414 if (location >= MaxLocation)
3415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003416 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003417 return false;
3418 }
3419
3420 const auto *programObject = context->getProgram(program);
3421 if (!programObject)
3422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003423 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003424 return false;
3425 }
3426
3427 if (!name)
3428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003429 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003430 return false;
3431 }
3432
3433 if (angle::BeginsWith(name, "gl_"))
3434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003435 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003436 return false;
3437 }
3438
3439 return true;
3440}
3441
3442bool ValidateProgramPathFragmentInputGen(Context *context,
3443 GLuint program,
3444 GLint location,
3445 GLenum genMode,
3446 GLint components,
3447 const GLfloat *coeffs)
3448{
3449 if (!context->getExtensions().pathRendering)
3450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003451 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003452 return false;
3453 }
3454
3455 const auto *programObject = context->getProgram(program);
3456 if (!programObject || programObject->isFlaggedForDeletion())
3457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003458 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003459 return false;
3460 }
3461
3462 if (!programObject->isLinked())
3463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003464 context->handleError(InvalidOperation() << "Program is not linked.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003465 return false;
3466 }
3467
3468 switch (genMode)
3469 {
3470 case GL_NONE:
3471 if (components != 0)
3472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003473 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003474 return false;
3475 }
3476 break;
3477
3478 case GL_OBJECT_LINEAR_CHROMIUM:
3479 case GL_EYE_LINEAR_CHROMIUM:
3480 case GL_CONSTANT_CHROMIUM:
3481 if (components < 1 || components > 4)
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 if (!coeffs)
3487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003488 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003489 return false;
3490 }
3491 break;
3492
3493 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003495 return false;
3496 }
3497
3498 // If the location is -1 then the command is silently ignored
3499 // and no further validation is needed.
3500 if (location == -1)
3501 return true;
3502
Jamie Madillbd044ed2017-06-05 12:59:21 -04003503 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003504
3505 if (!binding.valid)
3506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003507 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003508 return false;
3509 }
3510
3511 if (binding.type != GL_NONE)
3512 {
3513 GLint expectedComponents = 0;
3514 switch (binding.type)
3515 {
3516 case GL_FLOAT:
3517 expectedComponents = 1;
3518 break;
3519 case GL_FLOAT_VEC2:
3520 expectedComponents = 2;
3521 break;
3522 case GL_FLOAT_VEC3:
3523 expectedComponents = 3;
3524 break;
3525 case GL_FLOAT_VEC4:
3526 expectedComponents = 4;
3527 break;
3528 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003529 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003530 InvalidOperation()
3531 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003532 return false;
3533 }
3534 if (expectedComponents != components && genMode != GL_NONE)
3535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003536 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003537 return false;
3538 }
3539 }
3540 return true;
3541}
3542
Geoff Lang97073d12016-04-20 10:42:34 -07003543bool ValidateCopyTextureCHROMIUM(Context *context,
3544 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003545 GLint sourceLevel,
3546 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003547 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003548 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003549 GLint internalFormat,
3550 GLenum destType,
3551 GLboolean unpackFlipY,
3552 GLboolean unpackPremultiplyAlpha,
3553 GLboolean unpackUnmultiplyAlpha)
3554{
3555 if (!context->getExtensions().copyTexture)
3556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidOperation()
3558 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003559 return false;
3560 }
3561
Geoff Lang4f0e0032017-05-01 16:04:35 -04003562 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003563 if (source == nullptr)
3564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003566 return false;
3567 }
3568
3569 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003571 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003572 return false;
3573 }
3574
3575 GLenum sourceTarget = source->getTarget();
3576 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003577
3578 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003580 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003581 return false;
3582 }
3583
Geoff Lang4f0e0032017-05-01 16:04:35 -04003584 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3585 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3586 if (sourceWidth == 0 || sourceHeight == 0)
3587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003588 context->handleError(InvalidValue()
3589 << "The source level of the source texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003590 return false;
3591 }
3592
3593 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3594 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003597 return false;
3598 }
3599
Geoff Lang4f0e0032017-05-01 16:04:35 -04003600 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003601 if (dest == nullptr)
3602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidValue()
3604 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003605 return false;
3606 }
3607
Geoff Lang4f0e0032017-05-01 16:04:35 -04003608 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003610 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003611 return false;
3612 }
3613
Geoff Lang4f0e0032017-05-01 16:04:35 -04003614 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3615 sourceHeight))
3616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003617 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003618 return false;
3619 }
3620
Geoff Lang97073d12016-04-20 10:42:34 -07003621 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003623 context->handleError(InvalidOperation()
3624 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003625 return false;
3626 }
3627
Geoff Lang4f0e0032017-05-01 16:04:35 -04003628 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(
3631 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003632 return false;
3633 }
3634
Geoff Lang97073d12016-04-20 10:42:34 -07003635 if (dest->getImmutableFormat())
3636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003637 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003638 return false;
3639 }
3640
3641 return true;
3642}
3643
3644bool ValidateCopySubTextureCHROMIUM(Context *context,
3645 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003646 GLint sourceLevel,
3647 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003648 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003649 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003650 GLint xoffset,
3651 GLint yoffset,
3652 GLint x,
3653 GLint y,
3654 GLsizei width,
3655 GLsizei height,
3656 GLboolean unpackFlipY,
3657 GLboolean unpackPremultiplyAlpha,
3658 GLboolean unpackUnmultiplyAlpha)
3659{
3660 if (!context->getExtensions().copyTexture)
3661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003662 context->handleError(InvalidOperation()
3663 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003664 return false;
3665 }
3666
Geoff Lang4f0e0032017-05-01 16:04:35 -04003667 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003668 if (source == nullptr)
3669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003670 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003671 return false;
3672 }
3673
3674 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003677 return false;
3678 }
3679
3680 GLenum sourceTarget = source->getTarget();
3681 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003682
3683 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003686 return false;
3687 }
3688
3689 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3690 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003692 context->handleError(InvalidValue()
3693 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003694 return false;
3695 }
3696
3697 if (x < 0 || y < 0)
3698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003699 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003700 return false;
3701 }
3702
3703 if (width < 0 || height < 0)
3704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidValue() << "width and height cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003706 return false;
3707 }
3708
Geoff Lang4f0e0032017-05-01 16:04:35 -04003709 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3710 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003712 context->handleError(InvalidValue() << "Source texture not large enough to copy from.");
Geoff Lang97073d12016-04-20 10:42:34 -07003713 return false;
3714 }
3715
Geoff Lang4f0e0032017-05-01 16:04:35 -04003716 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3717 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003719 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003720 return false;
3721 }
3722
Geoff Lang4f0e0032017-05-01 16:04:35 -04003723 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003724 if (dest == nullptr)
3725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003726 context->handleError(InvalidValue()
3727 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003728 return false;
3729 }
3730
Geoff Lang4f0e0032017-05-01 16:04:35 -04003731 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003733 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003734 return false;
3735 }
3736
Geoff Lang4f0e0032017-05-01 16:04:35 -04003737 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003739 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003740 return false;
3741 }
3742
Geoff Lang4f0e0032017-05-01 16:04:35 -04003743 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(
3746 InvalidValue() << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003747 return false;
3748 }
3749
3750 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3751 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003753 context->handleError(InvalidOperation()
3754 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003755 return false;
3756 }
3757
3758 if (xoffset < 0 || yoffset < 0)
3759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003760 context->handleError(InvalidValue() << "xoffset and yoffset cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003761 return false;
3762 }
3763
Geoff Lang4f0e0032017-05-01 16:04:35 -04003764 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3765 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003767 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003768 return false;
3769 }
3770
3771 return true;
3772}
3773
Geoff Lang47110bf2016-04-20 11:13:22 -07003774bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3775{
3776 if (!context->getExtensions().copyCompressedTexture)
3777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidOperation()
3779 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003780 return false;
3781 }
3782
3783 const gl::Texture *source = context->getTexture(sourceId);
3784 if (source == nullptr)
3785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003786 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003787 return false;
3788 }
3789
3790 if (source->getTarget() != GL_TEXTURE_2D)
3791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003792 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003793 return false;
3794 }
3795
3796 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003798 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003799 return false;
3800 }
3801
3802 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3803 if (!sourceFormat.info->compressed)
3804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 context->handleError(InvalidOperation()
3806 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003807 return false;
3808 }
3809
3810 const gl::Texture *dest = context->getTexture(destId);
3811 if (dest == nullptr)
3812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003813 context->handleError(InvalidValue()
3814 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003815 return false;
3816 }
3817
3818 if (dest->getTarget() != GL_TEXTURE_2D)
3819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003820 context->handleError(InvalidValue()
3821 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003822 return false;
3823 }
3824
3825 if (dest->getImmutableFormat())
3826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003828 return false;
3829 }
3830
3831 return true;
3832}
3833
Martin Radev4c4c8e72016-08-04 12:25:34 +03003834bool ValidateCreateShader(Context *context, GLenum type)
3835{
3836 switch (type)
3837 {
3838 case GL_VERTEX_SHADER:
3839 case GL_FRAGMENT_SHADER:
3840 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003841
Martin Radev4c4c8e72016-08-04 12:25:34 +03003842 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003843 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003845 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003846 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003847 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003848 break;
3849
Martin Radev4c4c8e72016-08-04 12:25:34 +03003850 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003851 context->handleError(InvalidEnum() << "Unknown shader type.");
Martin Radev4c4c8e72016-08-04 12:25:34 +03003852 return false;
3853 }
Jamie Madill29639852016-09-02 15:00:09 -04003854
3855 return true;
3856}
3857
3858bool ValidateBufferData(ValidationContext *context,
3859 GLenum target,
3860 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003861 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003862 GLenum usage)
3863{
3864 if (size < 0)
3865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003866 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003867 return false;
3868 }
3869
3870 switch (usage)
3871 {
3872 case GL_STREAM_DRAW:
3873 case GL_STATIC_DRAW:
3874 case GL_DYNAMIC_DRAW:
3875 break;
3876
3877 case GL_STREAM_READ:
3878 case GL_STREAM_COPY:
3879 case GL_STATIC_READ:
3880 case GL_STATIC_COPY:
3881 case GL_DYNAMIC_READ:
3882 case GL_DYNAMIC_COPY:
3883 if (context->getClientMajorVersion() < 3)
3884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003886 return false;
3887 }
3888 break;
3889
3890 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003891 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003892 return false;
3893 }
3894
3895 if (!ValidBufferTarget(context, target))
3896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003897 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003898 return false;
3899 }
3900
3901 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3902
3903 if (!buffer)
3904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003905 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003906 return false;
3907 }
3908
3909 return true;
3910}
3911
3912bool ValidateBufferSubData(ValidationContext *context,
3913 GLenum target,
3914 GLintptr offset,
3915 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003916 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003917{
3918 if (size < 0 || offset < 0)
3919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003920 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003921 return false;
3922 }
3923
3924 if (!ValidBufferTarget(context, target))
3925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003926 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003927 return false;
3928 }
3929
3930 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3931
3932 if (!buffer)
3933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003935 return false;
3936 }
3937
3938 if (buffer->isMapped())
3939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003940 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003941 return false;
3942 }
3943
3944 // Check for possible overflow of size + offset
3945 angle::CheckedNumeric<size_t> checkedSize(size);
3946 checkedSize += offset;
3947 if (!checkedSize.IsValid())
3948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003949 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04003950 return false;
3951 }
3952
3953 if (size + offset > buffer->getSize())
3954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003955 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003956 return false;
3957 }
3958
Martin Radev4c4c8e72016-08-04 12:25:34 +03003959 return true;
3960}
3961
Geoff Langc339c4e2016-11-29 10:37:36 -05003962bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003963{
Geoff Langc339c4e2016-11-29 10:37:36 -05003964 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003966 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04003967 return false;
3968 }
3969
3970 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3971 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003972 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003974 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04003975 return false;
3976 }
3977
3978 return true;
3979}
3980
Jamie Madillef300b12016-10-07 15:12:09 -04003981bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3982{
3983 if (texture < GL_TEXTURE0 ||
3984 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003986 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04003987 return false;
3988 }
3989
3990 return true;
3991}
3992
3993bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3994{
3995 Program *programObject = GetValidProgram(context, program);
3996 if (!programObject)
3997 {
3998 return false;
3999 }
4000
4001 Shader *shaderObject = GetValidShader(context, shader);
4002 if (!shaderObject)
4003 {
4004 return false;
4005 }
4006
4007 switch (shaderObject->getType())
4008 {
4009 case GL_VERTEX_SHADER:
4010 {
4011 if (programObject->getAttachedVertexShader())
4012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004013 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004014 return false;
4015 }
4016 break;
4017 }
4018 case GL_FRAGMENT_SHADER:
4019 {
4020 if (programObject->getAttachedFragmentShader())
4021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004022 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004023 return false;
4024 }
4025 break;
4026 }
4027 case GL_COMPUTE_SHADER:
4028 {
4029 if (programObject->getAttachedComputeShader())
4030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004031 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004032 return false;
4033 }
4034 break;
4035 }
4036 default:
4037 UNREACHABLE();
4038 break;
4039 }
4040
4041 return true;
4042}
4043
Jamie Madill01a80ee2016-11-07 12:06:18 -05004044bool ValidateBindAttribLocation(ValidationContext *context,
4045 GLuint program,
4046 GLuint index,
4047 const GLchar *name)
4048{
4049 if (index >= MAX_VERTEX_ATTRIBS)
4050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004051 context->handleError(InvalidValue() << "Index exceeds MAX_VERTEX_ATTRIBS");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004052 return false;
4053 }
4054
4055 if (strncmp(name, "gl_", 3) == 0)
4056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004057 context->handleError(InvalidOperation() << "Cannot Bind built-in attributes");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004058 return false;
4059 }
4060
Geoff Langfc32e8b2017-05-31 14:16:59 -04004061 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4062 // shader-related entry points
4063 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004065 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004066 return false;
4067 }
4068
Jamie Madill01a80ee2016-11-07 12:06:18 -05004069 return GetValidProgram(context, program) != nullptr;
4070}
4071
4072bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4073{
4074 if (!ValidBufferTarget(context, target))
4075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidEnum() << "Invalid Buffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004077 return false;
4078 }
4079
4080 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4081 !context->isBufferGenerated(buffer))
4082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004083 context->handleError(InvalidOperation() << "Buffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004084 return false;
4085 }
4086
4087 return true;
4088}
4089
4090bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4091{
4092 if (!ValidFramebufferTarget(target))
4093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004094 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004095 return false;
4096 }
4097
4098 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4099 !context->isFramebufferGenerated(framebuffer))
4100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004101 context->handleError(InvalidOperation() << "Framebuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004102 return false;
4103 }
4104
4105 return true;
4106}
4107
4108bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4109{
4110 if (target != GL_RENDERBUFFER)
4111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004112 context->handleError(InvalidEnum() << "Invalid Renderbuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004113 return false;
4114 }
4115
4116 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4117 !context->isRenderbufferGenerated(renderbuffer))
4118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004119 context->handleError(InvalidOperation() << "Renderbuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004120 return false;
4121 }
4122
4123 return true;
4124}
4125
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004126static bool ValidBlendEquationMode(GLenum mode)
4127{
4128 switch (mode)
4129 {
4130 case GL_FUNC_ADD:
4131 case GL_FUNC_SUBTRACT:
4132 case GL_FUNC_REVERSE_SUBTRACT:
4133 case GL_MIN:
4134 case GL_MAX:
4135 return true;
4136
4137 default:
4138 return false;
4139 }
4140}
4141
Jamie Madillc1d770e2017-04-13 17:31:24 -04004142bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004143 GLfloat red,
4144 GLfloat green,
4145 GLfloat blue,
4146 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004147{
4148 return true;
4149}
4150
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004151bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4152{
4153 if (!ValidBlendEquationMode(mode))
4154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004155 context->handleError(InvalidEnum() << "Invalid blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004156 return false;
4157 }
4158
4159 return true;
4160}
4161
4162bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4163{
4164 if (!ValidBlendEquationMode(modeRGB))
4165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004166 context->handleError(InvalidEnum() << "Invalid RGB blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004167 return false;
4168 }
4169
4170 if (!ValidBlendEquationMode(modeAlpha))
4171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004172 context->handleError(InvalidEnum() << "Invalid alpha blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004173 return false;
4174 }
4175
4176 return true;
4177}
4178
4179bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4180{
4181 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4182}
4183
4184static bool ValidSrcBlendFunc(GLenum srcBlend)
4185{
4186 switch (srcBlend)
4187 {
4188 case GL_ZERO:
4189 case GL_ONE:
4190 case GL_SRC_COLOR:
4191 case GL_ONE_MINUS_SRC_COLOR:
4192 case GL_DST_COLOR:
4193 case GL_ONE_MINUS_DST_COLOR:
4194 case GL_SRC_ALPHA:
4195 case GL_ONE_MINUS_SRC_ALPHA:
4196 case GL_DST_ALPHA:
4197 case GL_ONE_MINUS_DST_ALPHA:
4198 case GL_CONSTANT_COLOR:
4199 case GL_ONE_MINUS_CONSTANT_COLOR:
4200 case GL_CONSTANT_ALPHA:
4201 case GL_ONE_MINUS_CONSTANT_ALPHA:
4202 case GL_SRC_ALPHA_SATURATE:
4203 return true;
4204
4205 default:
4206 return false;
4207 }
4208}
4209
4210static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4211{
4212 switch (dstBlend)
4213 {
4214 case GL_ZERO:
4215 case GL_ONE:
4216 case GL_SRC_COLOR:
4217 case GL_ONE_MINUS_SRC_COLOR:
4218 case GL_DST_COLOR:
4219 case GL_ONE_MINUS_DST_COLOR:
4220 case GL_SRC_ALPHA:
4221 case GL_ONE_MINUS_SRC_ALPHA:
4222 case GL_DST_ALPHA:
4223 case GL_ONE_MINUS_DST_ALPHA:
4224 case GL_CONSTANT_COLOR:
4225 case GL_ONE_MINUS_CONSTANT_COLOR:
4226 case GL_CONSTANT_ALPHA:
4227 case GL_ONE_MINUS_CONSTANT_ALPHA:
4228 return true;
4229
4230 case GL_SRC_ALPHA_SATURATE:
4231 return (contextMajorVersion >= 3);
4232
4233 default:
4234 return false;
4235 }
4236}
4237
4238bool ValidateBlendFuncSeparate(ValidationContext *context,
4239 GLenum srcRGB,
4240 GLenum dstRGB,
4241 GLenum srcAlpha,
4242 GLenum dstAlpha)
4243{
4244 if (!ValidSrcBlendFunc(srcRGB))
4245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004246 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004247 return false;
4248 }
4249
4250 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004252 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004253 return false;
4254 }
4255
4256 if (!ValidSrcBlendFunc(srcAlpha))
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(dstAlpha, 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
Frank Henigman146e8a12017-03-02 23:22:37 -05004268 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4269 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004270 {
4271 bool constantColorUsed =
4272 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4273 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4274
4275 bool constantAlphaUsed =
4276 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4277 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4278
4279 if (constantColorUsed && constantAlphaUsed)
4280 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004281 const char *msg;
4282 if (context->getExtensions().webglCompatibility)
4283 {
4284 msg =
4285 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4286 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4287 }
4288 else
4289 {
4290 msg =
4291 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4292 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4293 "implementation.";
4294 ERR() << msg;
4295 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004296 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004297 return false;
4298 }
4299 }
4300
4301 return true;
4302}
4303
Geoff Langc339c4e2016-11-29 10:37:36 -05004304bool ValidateGetString(Context *context, GLenum name)
4305{
4306 switch (name)
4307 {
4308 case GL_VENDOR:
4309 case GL_RENDERER:
4310 case GL_VERSION:
4311 case GL_SHADING_LANGUAGE_VERSION:
4312 case GL_EXTENSIONS:
4313 break;
4314
4315 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4316 if (!context->getExtensions().requestExtension)
4317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004318 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004319 return false;
4320 }
4321 break;
4322
4323 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004324 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004325 return false;
4326 }
4327
4328 return true;
4329}
4330
Geoff Lang47c48082016-12-07 15:38:13 -05004331bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4332{
4333 if (width <= 0.0f || isNaN(width))
4334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004335 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004336 return false;
4337 }
4338
4339 return true;
4340}
4341
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004342bool ValidateVertexAttribPointer(ValidationContext *context,
4343 GLuint index,
4344 GLint size,
4345 GLenum type,
4346 GLboolean normalized,
4347 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004348 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004349{
Shao80957d92017-02-20 21:25:59 +08004350 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004351 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004352 return false;
4353 }
4354
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004355 if (stride < 0)
4356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004357 context->handleError(InvalidValue() << "stride cannot be negative.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004358 return false;
4359 }
4360
Shao80957d92017-02-20 21:25:59 +08004361 const Caps &caps = context->getCaps();
4362 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004363 {
Shao80957d92017-02-20 21:25:59 +08004364 if (stride > caps.maxVertexAttribStride)
4365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004366 context->handleError(InvalidValue()
4367 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004368 return false;
4369 }
4370
4371 if (index >= caps.maxVertexAttribBindings)
4372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004373 context->handleError(InvalidValue()
4374 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004375 return false;
4376 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004377 }
4378
4379 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4380 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4381 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4382 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004383 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4384 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004385 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004387 context
4388 ->handleError(InvalidOperation()
4389 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004390 return false;
4391 }
4392
4393 if (context->getExtensions().webglCompatibility)
4394 {
4395 // WebGL 1.0 [Section 6.14] Fixed point support
4396 // The WebGL API does not support the GL_FIXED data type.
4397 if (type == GL_FIXED)
4398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004399 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004400 return false;
4401 }
4402
Geoff Lang2d62ab72017-03-23 16:54:40 -04004403 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004404 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004405 return false;
4406 }
4407 }
4408
4409 return true;
4410}
4411
Jamie Madill876429b2017-04-20 15:46:24 -04004412bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004413{
4414 if (context->getExtensions().webglCompatibility && zNear > zFar)
4415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004416 context->handleError(InvalidOperation() << "Depth near > far.");
Frank Henigman6137ddc2017-02-10 18:55:07 -05004417 return false;
4418 }
4419
4420 return true;
4421}
4422
Jamie Madille8fb6402017-02-14 17:56:40 -05004423bool ValidateRenderbufferStorage(ValidationContext *context,
4424 GLenum target,
4425 GLenum internalformat,
4426 GLsizei width,
4427 GLsizei height)
4428{
4429 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4430 height);
4431}
4432
4433bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4434 GLenum target,
4435 GLsizei samples,
4436 GLenum internalformat,
4437 GLsizei width,
4438 GLsizei height)
4439{
4440 if (!context->getExtensions().framebufferMultisample)
4441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004442 context->handleError(InvalidOperation()
4443 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004444 return false;
4445 }
4446
4447 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4448 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4449 // generated.
4450 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004452 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004453 return false;
4454 }
4455
4456 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4457 // the specified storage. This is different than ES 3.0 in which a sample number higher
4458 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4459 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4460 if (context->getClientMajorVersion() >= 3)
4461 {
4462 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4463 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004465 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004466 return false;
4467 }
4468 }
4469
4470 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4471 width, height);
4472}
4473
Jamie Madillc1d770e2017-04-13 17:31:24 -04004474bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4475{
4476 if (!ValidFramebufferTarget(target))
4477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004478 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004479 return false;
4480 }
4481
4482 return true;
4483}
4484
4485bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004486 GLfloat red,
4487 GLfloat green,
4488 GLfloat blue,
4489 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004490{
4491 return true;
4492}
4493
Jamie Madill876429b2017-04-20 15:46:24 -04004494bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004495{
4496 return true;
4497}
4498
4499bool ValidateClearStencil(ValidationContext *context, GLint s)
4500{
4501 return true;
4502}
4503
4504bool ValidateColorMask(ValidationContext *context,
4505 GLboolean red,
4506 GLboolean green,
4507 GLboolean blue,
4508 GLboolean alpha)
4509{
4510 return true;
4511}
4512
4513bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4514{
4515 return true;
4516}
4517
4518bool ValidateCreateProgram(ValidationContext *context)
4519{
4520 return true;
4521}
4522
4523bool ValidateCullFace(ValidationContext *context, GLenum mode)
4524{
4525 switch (mode)
4526 {
4527 case GL_FRONT:
4528 case GL_BACK:
4529 case GL_FRONT_AND_BACK:
4530 break;
4531
4532 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004533 context->handleError(InvalidEnum() << "Invalid cull face parameter");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004534 return false;
4535 }
4536
4537 return true;
4538}
4539
4540bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4541{
4542 if (program == 0)
4543 {
4544 return false;
4545 }
4546
4547 if (!context->getProgram(program))
4548 {
4549 if (context->getShader(program))
4550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004551 context->handleError(InvalidOperation() << "Shader handle passed to DeleteProgram");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004552 return false;
4553 }
4554 else
4555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004556 context->handleError(InvalidValue() << "Invalid program handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004557 return false;
4558 }
4559 }
4560
4561 return true;
4562}
4563
4564bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4565{
4566 if (shader == 0)
4567 {
4568 return false;
4569 }
4570
4571 if (!context->getShader(shader))
4572 {
4573 if (context->getProgram(shader))
4574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004575 context->handleError(InvalidOperation() << "Program handle passed to DeleteShader");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004576 return false;
4577 }
4578 else
4579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004580 context->handleError(InvalidValue() << "Invalid shader handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004581 return false;
4582 }
4583 }
4584
4585 return true;
4586}
4587
4588bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4589{
4590 switch (func)
4591 {
4592 case GL_NEVER:
4593 case GL_ALWAYS:
4594 case GL_LESS:
4595 case GL_LEQUAL:
4596 case GL_EQUAL:
4597 case GL_GREATER:
4598 case GL_GEQUAL:
4599 case GL_NOTEQUAL:
4600 break;
4601
4602 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004603 context->handleError(InvalidEnum() << "Invalid depth function");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004604 return false;
4605 }
4606
4607 return true;
4608}
4609
4610bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4611{
4612 return true;
4613}
4614
4615bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4616{
4617 Program *programObject = GetValidProgram(context, program);
4618 if (!programObject)
4619 {
4620 return false;
4621 }
4622
4623 Shader *shaderObject = GetValidShader(context, shader);
4624 if (!shaderObject)
4625 {
4626 return false;
4627 }
4628
4629 const Shader *attachedShader = nullptr;
4630
4631 switch (shaderObject->getType())
4632 {
4633 case GL_VERTEX_SHADER:
4634 {
4635 attachedShader = programObject->getAttachedVertexShader();
4636 break;
4637 }
4638 case GL_FRAGMENT_SHADER:
4639 {
4640 attachedShader = programObject->getAttachedFragmentShader();
4641 break;
4642 }
4643 case GL_COMPUTE_SHADER:
4644 {
4645 attachedShader = programObject->getAttachedComputeShader();
4646 break;
4647 }
4648 default:
4649 UNREACHABLE();
4650 return false;
4651 }
4652
4653 if (attachedShader != shaderObject)
4654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004655 context->handleError(InvalidOperation() << "Cannot detach non-attached shader.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004656 return false;
4657 }
4658
4659 return true;
4660}
4661
4662bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4663{
4664 if (index >= MAX_VERTEX_ATTRIBS)
4665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004666 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004667 return false;
4668 }
4669
4670 return true;
4671}
4672
4673bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4674{
4675 if (index >= MAX_VERTEX_ATTRIBS)
4676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004677 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004678 return false;
4679 }
4680
4681 return true;
4682}
4683
4684bool ValidateFinish(ValidationContext *context)
4685{
4686 return true;
4687}
4688
4689bool ValidateFlush(ValidationContext *context)
4690{
4691 return true;
4692}
4693
4694bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4695{
4696 switch (mode)
4697 {
4698 case GL_CW:
4699 case GL_CCW:
4700 break;
4701 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004702 context->handleError(InvalidEnum() << "Invalid mode for FrontFace");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004703 return false;
4704 }
4705
4706 return true;
4707}
4708
4709bool ValidateGetActiveAttrib(ValidationContext *context,
4710 GLuint program,
4711 GLuint index,
4712 GLsizei bufsize,
4713 GLsizei *length,
4714 GLint *size,
4715 GLenum *type,
4716 GLchar *name)
4717{
4718 if (bufsize < 0)
4719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004720 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004721 return false;
4722 }
4723
4724 Program *programObject = GetValidProgram(context, program);
4725
4726 if (!programObject)
4727 {
4728 return false;
4729 }
4730
4731 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004733 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004734 return false;
4735 }
4736
4737 return true;
4738}
4739
4740bool ValidateGetActiveUniform(ValidationContext *context,
4741 GLuint program,
4742 GLuint index,
4743 GLsizei bufsize,
4744 GLsizei *length,
4745 GLint *size,
4746 GLenum *type,
4747 GLchar *name)
4748{
4749 if (bufsize < 0)
4750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004751 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004752 return false;
4753 }
4754
4755 Program *programObject = GetValidProgram(context, program);
4756
4757 if (!programObject)
4758 {
4759 return false;
4760 }
4761
4762 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004764 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004765 return false;
4766 }
4767
4768 return true;
4769}
4770
4771bool ValidateGetAttachedShaders(ValidationContext *context,
4772 GLuint program,
4773 GLsizei maxcount,
4774 GLsizei *count,
4775 GLuint *shaders)
4776{
4777 if (maxcount < 0)
4778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004779 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004780 return false;
4781 }
4782
4783 Program *programObject = GetValidProgram(context, program);
4784
4785 if (!programObject)
4786 {
4787 return false;
4788 }
4789
4790 return true;
4791}
4792
4793bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4794{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004795 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4796 // shader-related entry points
4797 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004799 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004800 return false;
4801 }
4802
Jamie Madillc1d770e2017-04-13 17:31:24 -04004803 Program *programObject = GetValidProgram(context, program);
4804
4805 if (!programObject)
4806 {
4807 return false;
4808 }
4809
4810 if (!programObject->isLinked())
4811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004812 context->handleError(InvalidOperation() << "program not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004813 return false;
4814 }
4815
4816 return true;
4817}
4818
4819bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4820{
4821 GLenum nativeType;
4822 unsigned int numParams = 0;
4823 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4824}
4825
4826bool ValidateGetError(ValidationContext *context)
4827{
4828 return true;
4829}
4830
4831bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4832{
4833 GLenum nativeType;
4834 unsigned int numParams = 0;
4835 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4836}
4837
4838bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4839{
4840 GLenum nativeType;
4841 unsigned int numParams = 0;
4842 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4843}
4844
4845bool ValidateGetProgramInfoLog(ValidationContext *context,
4846 GLuint program,
4847 GLsizei bufsize,
4848 GLsizei *length,
4849 GLchar *infolog)
4850{
4851 if (bufsize < 0)
4852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004853 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004854 return false;
4855 }
4856
4857 Program *programObject = GetValidProgram(context, program);
4858 if (!programObject)
4859 {
4860 return false;
4861 }
4862
4863 return true;
4864}
4865
4866bool ValidateGetShaderInfoLog(ValidationContext *context,
4867 GLuint shader,
4868 GLsizei bufsize,
4869 GLsizei *length,
4870 GLchar *infolog)
4871{
4872 if (bufsize < 0)
4873 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004874 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004875 return false;
4876 }
4877
4878 Shader *shaderObject = GetValidShader(context, shader);
4879 if (!shaderObject)
4880 {
4881 return false;
4882 }
4883
4884 return true;
4885}
4886
4887bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4888 GLenum shadertype,
4889 GLenum precisiontype,
4890 GLint *range,
4891 GLint *precision)
4892{
4893 switch (shadertype)
4894 {
4895 case GL_VERTEX_SHADER:
4896 case GL_FRAGMENT_SHADER:
4897 break;
4898 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004899 context->handleError(InvalidOperation()
4900 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004901 return false;
4902 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004903 context->handleError(InvalidEnum() << "invalid shader type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004904 return false;
4905 }
4906
4907 switch (precisiontype)
4908 {
4909 case GL_LOW_FLOAT:
4910 case GL_MEDIUM_FLOAT:
4911 case GL_HIGH_FLOAT:
4912 case GL_LOW_INT:
4913 case GL_MEDIUM_INT:
4914 case GL_HIGH_INT:
4915 break;
4916
4917 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004918 context->handleError(InvalidEnum() << "invalid precision type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004919 return false;
4920 }
4921
4922 return true;
4923}
4924
4925bool ValidateGetShaderSource(ValidationContext *context,
4926 GLuint shader,
4927 GLsizei bufsize,
4928 GLsizei *length,
4929 GLchar *source)
4930{
4931 if (bufsize < 0)
4932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004933 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004934 return false;
4935 }
4936
4937 Shader *shaderObject = GetValidShader(context, shader);
4938 if (!shaderObject)
4939 {
4940 return false;
4941 }
4942
4943 return true;
4944}
4945
4946bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4947{
4948 if (strstr(name, "gl_") == name)
4949 {
4950 return false;
4951 }
4952
Geoff Langfc32e8b2017-05-31 14:16:59 -04004953 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4954 // shader-related entry points
4955 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004957 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004958 return false;
4959 }
4960
Jamie Madillc1d770e2017-04-13 17:31:24 -04004961 Program *programObject = GetValidProgram(context, program);
4962
4963 if (!programObject)
4964 {
4965 return false;
4966 }
4967
4968 if (!programObject->isLinked())
4969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004970 context->handleError(InvalidOperation() << "program is not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004971 return false;
4972 }
4973
4974 return true;
4975}
4976
4977bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4978{
4979 switch (mode)
4980 {
4981 case GL_FASTEST:
4982 case GL_NICEST:
4983 case GL_DONT_CARE:
4984 break;
4985
4986 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004987 context->handleError(InvalidEnum() << "invalid hint mode.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004988 return false;
4989 }
4990
4991 switch (target)
4992 {
4993 case GL_GENERATE_MIPMAP_HINT:
4994 break;
4995
4996 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4997 if (!context->getExtensions().standardDerivatives)
4998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004999 context->handleError(InvalidOperation()
5000 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005001 return false;
5002 }
5003 break;
5004
5005 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005006 context->handleError(InvalidEnum() << "invalid hint target.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005007 return false;
5008 }
5009
5010 return true;
5011}
5012
5013bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5014{
5015 return true;
5016}
5017
5018bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5019{
5020 return true;
5021}
5022
5023bool ValidateIsProgram(ValidationContext *context, GLuint program)
5024{
5025 return true;
5026}
5027
5028bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5029{
5030 return true;
5031}
5032
5033bool ValidateIsShader(ValidationContext *context, GLuint shader)
5034{
5035 return true;
5036}
5037
5038bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5039{
5040 return true;
5041}
5042
5043bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5044{
5045 if (context->getClientMajorVersion() < 3)
5046 {
5047 switch (pname)
5048 {
5049 case GL_UNPACK_IMAGE_HEIGHT:
5050 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005051 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005052 return false;
5053
5054 case GL_UNPACK_ROW_LENGTH:
5055 case GL_UNPACK_SKIP_ROWS:
5056 case GL_UNPACK_SKIP_PIXELS:
5057 if (!context->getExtensions().unpackSubimage)
5058 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005059 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005060 return false;
5061 }
5062 break;
5063
5064 case GL_PACK_ROW_LENGTH:
5065 case GL_PACK_SKIP_ROWS:
5066 case GL_PACK_SKIP_PIXELS:
5067 if (!context->getExtensions().packSubimage)
5068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005069 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005070 return false;
5071 }
5072 break;
5073 }
5074 }
5075
5076 if (param < 0)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005079 return false;
5080 }
5081
5082 switch (pname)
5083 {
5084 case GL_UNPACK_ALIGNMENT:
5085 if (param != 1 && param != 2 && param != 4 && param != 8)
5086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005087 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005088 return false;
5089 }
5090 break;
5091
5092 case GL_PACK_ALIGNMENT:
5093 if (param != 1 && param != 2 && param != 4 && param != 8)
5094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005095 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005096 return false;
5097 }
5098 break;
5099
5100 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5101 case GL_UNPACK_ROW_LENGTH:
5102 case GL_UNPACK_IMAGE_HEIGHT:
5103 case GL_UNPACK_SKIP_IMAGES:
5104 case GL_UNPACK_SKIP_ROWS:
5105 case GL_UNPACK_SKIP_PIXELS:
5106 case GL_PACK_ROW_LENGTH:
5107 case GL_PACK_SKIP_ROWS:
5108 case GL_PACK_SKIP_PIXELS:
5109 break;
5110
5111 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005112 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005113 return false;
5114 }
5115
5116 return true;
5117}
5118
5119bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5120{
5121 return true;
5122}
5123
5124bool ValidateReleaseShaderCompiler(ValidationContext *context)
5125{
5126 return true;
5127}
5128
Jamie Madill876429b2017-04-20 15:46:24 -04005129bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005130{
5131 return true;
5132}
5133
5134bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5135{
5136 if (width < 0 || height < 0)
5137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005138 context->handleError(InvalidValue() << "Scissor width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005139 return false;
5140 }
5141
5142 return true;
5143}
5144
5145bool ValidateShaderBinary(ValidationContext *context,
5146 GLsizei n,
5147 const GLuint *shaders,
5148 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005149 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005150 GLsizei length)
5151{
5152 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5153 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5154 shaderBinaryFormats.end())
5155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005156 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005157 return false;
5158 }
5159
5160 return true;
5161}
5162
5163bool ValidateShaderSource(ValidationContext *context,
5164 GLuint shader,
5165 GLsizei count,
5166 const GLchar *const *string,
5167 const GLint *length)
5168{
5169 if (count < 0)
5170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005171 context->handleError(InvalidValue() << "Count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005172 return false;
5173 }
5174
Geoff Langfc32e8b2017-05-31 14:16:59 -04005175 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5176 // shader-related entry points
5177 if (context->getExtensions().webglCompatibility)
5178 {
5179 for (GLsizei i = 0; i < count; i++)
5180 {
5181 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
5182 if (!IsValidESSLString(string[i], len))
5183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005184 context->handleError(InvalidValue() << "Shader source contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04005185 return false;
5186 }
5187 }
5188 }
5189
Jamie Madillc1d770e2017-04-13 17:31:24 -04005190 Shader *shaderObject = GetValidShader(context, shader);
5191 if (!shaderObject)
5192 {
5193 return false;
5194 }
5195
5196 return true;
5197}
5198
5199bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5200{
5201 if (!IsValidStencilFunc(func))
5202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005203 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005204 return false;
5205 }
5206
5207 return true;
5208}
5209
5210bool ValidateStencilFuncSeparate(ValidationContext *context,
5211 GLenum face,
5212 GLenum func,
5213 GLint ref,
5214 GLuint mask)
5215{
5216 if (!IsValidStencilFace(face))
5217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005218 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005219 return false;
5220 }
5221
5222 if (!IsValidStencilFunc(func))
5223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005224 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005225 return false;
5226 }
5227
5228 return true;
5229}
5230
5231bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5232{
5233 return true;
5234}
5235
5236bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5237{
5238 if (!IsValidStencilFace(face))
5239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005240 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005241 return false;
5242 }
5243
5244 return true;
5245}
5246
5247bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5248{
5249 if (!IsValidStencilOp(fail))
5250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005251 context->handleError(InvalidEnum() << "Invalid stencil fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005252 return false;
5253 }
5254
5255 if (!IsValidStencilOp(zfail))
5256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005257 context->handleError(InvalidEnum() << "Invalid stencil z fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005258 return false;
5259 }
5260
5261 if (!IsValidStencilOp(zpass))
5262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005263 context->handleError(InvalidEnum() << "Invalid stencil z pass op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005264 return false;
5265 }
5266
5267 return true;
5268}
5269
5270bool ValidateStencilOpSeparate(ValidationContext *context,
5271 GLenum face,
5272 GLenum fail,
5273 GLenum zfail,
5274 GLenum zpass)
5275{
5276 if (!IsValidStencilFace(face))
5277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005278 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005279 return false;
5280 }
5281
5282 return ValidateStencilOp(context, fail, zfail, zpass);
5283}
5284
5285bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5286{
5287 return ValidateUniform(context, GL_FLOAT, location, 1);
5288}
5289
5290bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5291{
5292 return ValidateUniform(context, GL_FLOAT, location, count);
5293}
5294
Jamie Madillbe849e42017-05-02 15:49:00 -04005295bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5296{
5297 return ValidateUniform1iv(context, location, 1, &x);
5298}
5299
Jamie Madillc1d770e2017-04-13 17:31:24 -04005300bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5301{
5302 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5303}
5304
5305bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5306{
5307 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5308}
5309
5310bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5311{
5312 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5313}
5314
5315bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5316{
5317 return ValidateUniform(context, GL_INT_VEC2, location, count);
5318}
5319
5320bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5321{
5322 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5323}
5324
5325bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5326{
5327 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5328}
5329
5330bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5331{
5332 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5333}
5334
5335bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5336{
5337 return ValidateUniform(context, GL_INT_VEC3, location, count);
5338}
5339
5340bool ValidateUniform4f(ValidationContext *context,
5341 GLint location,
5342 GLfloat x,
5343 GLfloat y,
5344 GLfloat z,
5345 GLfloat w)
5346{
5347 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5348}
5349
5350bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5351{
5352 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5353}
5354
5355bool ValidateUniform4i(ValidationContext *context,
5356 GLint location,
5357 GLint x,
5358 GLint y,
5359 GLint z,
5360 GLint w)
5361{
5362 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5363}
5364
5365bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5366{
5367 return ValidateUniform(context, GL_INT_VEC4, location, count);
5368}
5369
5370bool ValidateUniformMatrix2fv(ValidationContext *context,
5371 GLint location,
5372 GLsizei count,
5373 GLboolean transpose,
5374 const GLfloat *value)
5375{
5376 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5377}
5378
5379bool ValidateUniformMatrix3fv(ValidationContext *context,
5380 GLint location,
5381 GLsizei count,
5382 GLboolean transpose,
5383 const GLfloat *value)
5384{
5385 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5386}
5387
5388bool ValidateUniformMatrix4fv(ValidationContext *context,
5389 GLint location,
5390 GLsizei count,
5391 GLboolean transpose,
5392 const GLfloat *value)
5393{
5394 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5395}
5396
5397bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5398{
5399 Program *programObject = GetValidProgram(context, program);
5400
5401 if (!programObject)
5402 {
5403 return false;
5404 }
5405
5406 return true;
5407}
5408
5409bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5410{
5411 if (index >= MAX_VERTEX_ATTRIBS)
5412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005413 context->handleError(InvalidValue() << "Vertex attrib index out of range.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005414 return false;
5415 }
5416
5417 return true;
5418}
5419
5420bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5421{
5422 return ValidateVertexAttribIndex(context, index);
5423}
5424
5425bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5426{
5427 return ValidateVertexAttribIndex(context, index);
5428}
5429
5430bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5431{
5432 return ValidateVertexAttribIndex(context, index);
5433}
5434
5435bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5436{
5437 return ValidateVertexAttribIndex(context, index);
5438}
5439
5440bool ValidateVertexAttrib3f(ValidationContext *context,
5441 GLuint index,
5442 GLfloat x,
5443 GLfloat y,
5444 GLfloat z)
5445{
5446 return ValidateVertexAttribIndex(context, index);
5447}
5448
5449bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5450{
5451 return ValidateVertexAttribIndex(context, index);
5452}
5453
5454bool ValidateVertexAttrib4f(ValidationContext *context,
5455 GLuint index,
5456 GLfloat x,
5457 GLfloat y,
5458 GLfloat z,
5459 GLfloat w)
5460{
5461 return ValidateVertexAttribIndex(context, index);
5462}
5463
5464bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5465{
5466 return ValidateVertexAttribIndex(context, index);
5467}
5468
5469bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5470{
5471 if (width < 0 || height < 0)
5472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005473 context->handleError(InvalidValue() << "Viewport width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005474 return false;
5475 }
5476
5477 return true;
5478}
5479
5480bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5481{
5482 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5483}
5484
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005485bool ValidateDrawElements(ValidationContext *context,
5486 GLenum mode,
5487 GLsizei count,
5488 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005489 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005490{
5491 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5492}
5493
Jamie Madillbe849e42017-05-02 15:49:00 -04005494bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5495 GLenum target,
5496 GLenum attachment,
5497 GLenum pname,
5498 GLint *params)
5499{
5500 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5501 nullptr);
5502}
5503
5504bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5505{
5506 return ValidateGetProgramivBase(context, program, pname, nullptr);
5507}
5508
5509bool ValidateCopyTexImage2D(ValidationContext *context,
5510 GLenum target,
5511 GLint level,
5512 GLenum internalformat,
5513 GLint x,
5514 GLint y,
5515 GLsizei width,
5516 GLsizei height,
5517 GLint border)
5518{
5519 if (context->getClientMajorVersion() < 3)
5520 {
5521 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5522 0, x, y, width, height, border);
5523 }
5524
5525 ASSERT(context->getClientMajorVersion() == 3);
5526 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5527 0, x, y, width, height, border);
5528}
5529
5530bool ValidateCopyTexSubImage2D(Context *context,
5531 GLenum target,
5532 GLint level,
5533 GLint xoffset,
5534 GLint yoffset,
5535 GLint x,
5536 GLint y,
5537 GLsizei width,
5538 GLsizei height)
5539{
5540 if (context->getClientMajorVersion() < 3)
5541 {
5542 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5543 yoffset, x, y, width, height, 0);
5544 }
5545
5546 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5547 yoffset, 0, x, y, width, height, 0);
5548}
5549
5550bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5551{
5552 return ValidateGenOrDelete(context, n);
5553}
5554
5555bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5556{
5557 return ValidateGenOrDelete(context, n);
5558}
5559
5560bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5561{
5562 return ValidateGenOrDelete(context, n);
5563}
5564
5565bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5566{
5567 return ValidateGenOrDelete(context, n);
5568}
5569
5570bool ValidateDisable(Context *context, GLenum cap)
5571{
5572 if (!ValidCap(context, cap, false))
5573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005574 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005575 return false;
5576 }
5577
5578 return true;
5579}
5580
5581bool ValidateEnable(Context *context, GLenum cap)
5582{
5583 if (!ValidCap(context, cap, false))
5584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005585 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588
5589 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5590 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5591 {
5592 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005593 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005594
5595 // We also output an error message to the debugger window if tracing is active, so that
5596 // developers can see the error message.
5597 ERR() << errorMessage;
5598 return false;
5599 }
5600
5601 return true;
5602}
5603
5604bool ValidateFramebufferRenderbuffer(Context *context,
5605 GLenum target,
5606 GLenum attachment,
5607 GLenum renderbuffertarget,
5608 GLuint renderbuffer)
5609{
5610 if (!ValidFramebufferTarget(target) ||
5611 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005613 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005614 return false;
5615 }
5616
5617 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5618 renderbuffertarget, renderbuffer);
5619}
5620
5621bool ValidateFramebufferTexture2D(Context *context,
5622 GLenum target,
5623 GLenum attachment,
5624 GLenum textarget,
5625 GLuint texture,
5626 GLint level)
5627{
5628 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5629 // extension
5630 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5631 level != 0)
5632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005633 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005634 return false;
5635 }
5636
5637 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5638 {
5639 return false;
5640 }
5641
5642 if (texture != 0)
5643 {
5644 gl::Texture *tex = context->getTexture(texture);
5645 ASSERT(tex);
5646
5647 const gl::Caps &caps = context->getCaps();
5648
5649 switch (textarget)
5650 {
5651 case GL_TEXTURE_2D:
5652 {
5653 if (level > gl::log2(caps.max2DTextureSize))
5654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005655 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005656 return false;
5657 }
5658 if (tex->getTarget() != GL_TEXTURE_2D)
5659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005660 context->handleError(InvalidOperation()
5661 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005662 return false;
5663 }
5664 }
5665 break;
5666
5667 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5668 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5669 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5670 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5671 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5672 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5673 {
5674 if (level > gl::log2(caps.maxCubeMapTextureSize))
5675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005676 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 return false;
5678 }
5679 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005681 context->handleError(InvalidOperation()
5682 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005683 return false;
5684 }
5685 }
5686 break;
5687
5688 case GL_TEXTURE_2D_MULTISAMPLE:
5689 {
5690 if (context->getClientVersion() < ES_3_1)
5691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005692 context->handleError(InvalidOperation()
5693 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 return false;
5695 }
5696
5697 if (level != 0)
5698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005699 context->handleError(InvalidValue()
5700 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005701 return false;
5702 }
5703 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005705 context->handleError(InvalidOperation()
5706 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005707 return false;
5708 }
5709 }
5710 break;
5711
5712 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005713 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005714 return false;
5715 }
5716
5717 const Format &format = tex->getFormat(textarget, level);
5718 if (format.info->compressed)
5719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005720 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 return false;
5722 }
5723 }
5724
5725 return true;
5726}
5727
5728bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5729{
5730 return ValidateGenOrDelete(context, n);
5731}
5732
5733bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5734{
5735 return ValidateGenOrDelete(context, n);
5736}
5737
5738bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5739{
5740 return ValidateGenOrDelete(context, n);
5741}
5742
5743bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5744{
5745 return ValidateGenOrDelete(context, n);
5746}
5747
5748bool ValidateGenerateMipmap(Context *context, GLenum target)
5749{
5750 if (!ValidTextureTarget(context, target))
5751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005752 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005753 return false;
5754 }
5755
5756 Texture *texture = context->getTargetTexture(target);
5757
5758 if (texture == nullptr)
5759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005760 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 return false;
5762 }
5763
5764 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5765
5766 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5767 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5768 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005770 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005771 return false;
5772 }
5773
5774 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5775 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5776 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5777
5778 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5779 // unsized formats or that are color renderable and filterable. Since we do not track if
5780 // the texture was created with sized or unsized format (only sized formats are stored),
5781 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5782 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5783 // textures since they're the only texture format that can be created with unsized formats
5784 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5785 // was the last version to use add them.
5786 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5787 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005789 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005790 return false;
5791 }
5792
Geoff Lang65ac5b92017-05-01 13:16:30 -04005793 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5794 bool supportsSRGBMipmapGeneration =
5795 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5796 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005798 context->handleError(InvalidOperation()
5799 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005800 return false;
5801 }
5802
5803 // Non-power of 2 ES2 check
5804 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5805 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5806 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5807 {
5808 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005809 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005810 return false;
5811 }
5812
5813 // Cube completeness check
5814 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005816 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005817 return false;
5818 }
5819
5820 return true;
5821}
5822
5823bool ValidateGetBufferParameteriv(ValidationContext *context,
5824 GLenum target,
5825 GLenum pname,
5826 GLint *params)
5827{
5828 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5829}
5830
5831bool ValidateGetRenderbufferParameteriv(Context *context,
5832 GLenum target,
5833 GLenum pname,
5834 GLint *params)
5835{
5836 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5837}
5838
5839bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5840{
5841 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5842}
5843
5844bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5845{
5846 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5847}
5848
5849bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5850{
5851 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5852}
5853
5854bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5855{
5856 return ValidateGetUniformBase(context, program, location);
5857}
5858
5859bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5860{
5861 return ValidateGetUniformBase(context, program, location);
5862}
5863
5864bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5865{
5866 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5867}
5868
5869bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5870{
5871 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5872}
5873
5874bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5875{
5876 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5877}
5878
5879bool ValidateIsEnabled(Context *context, GLenum cap)
5880{
5881 if (!ValidCap(context, cap, true))
5882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005883 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005884 return false;
5885 }
5886
5887 return true;
5888}
5889
5890bool ValidateLinkProgram(Context *context, GLuint program)
5891{
5892 if (context->hasActiveTransformFeedback(program))
5893 {
5894 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005895 context->handleError(InvalidOperation() << "Cannot link program while program is "
5896 "associated with an active transform "
5897 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005898 return false;
5899 }
5900
5901 Program *programObject = GetValidProgram(context, program);
5902 if (!programObject)
5903 {
5904 return false;
5905 }
5906
5907 return true;
5908}
5909
5910bool ValidateReadPixels(ValidationContext *context,
5911 GLint x,
5912 GLint y,
5913 GLsizei width,
5914 GLsizei height,
5915 GLenum format,
5916 GLenum type,
5917 void *pixels)
5918{
5919 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5920 nullptr, pixels);
5921}
5922
5923bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5924{
5925 return ValidateTexParameterBase(context, target, pname, -1, &param);
5926}
5927
5928bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5929{
5930 return ValidateTexParameterBase(context, target, pname, -1, params);
5931}
5932
5933bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5934{
5935 return ValidateTexParameterBase(context, target, pname, -1, &param);
5936}
5937
5938bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5939{
5940 return ValidateTexParameterBase(context, target, pname, -1, params);
5941}
5942
5943bool ValidateUseProgram(Context *context, GLuint program)
5944{
5945 if (program != 0)
5946 {
5947 Program *programObject = context->getProgram(program);
5948 if (!programObject)
5949 {
5950 // ES 3.1.0 section 7.3 page 72
5951 if (context->getShader(program))
5952 {
5953 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005954 InvalidOperation()
5955 << "Attempted to use a single shader instead of a shader program.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005956 return false;
5957 }
5958 else
5959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005960 context->handleError(InvalidValue() << "Program invalid.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005961 return false;
5962 }
5963 }
5964 if (!programObject->isLinked())
5965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005966 context->handleError(InvalidOperation() << "Program not linked.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005967 return false;
5968 }
5969 }
5970 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5971 {
5972 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005973 context
5974 ->handleError(InvalidOperation()
5975 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005976 return false;
5977 }
5978
5979 return true;
5980}
5981
Jamie Madillc29968b2016-01-20 11:17:23 -05005982} // namespace gl