blob: 8bd1469b4c6a38784d9d6a90850c5357a7c13134 [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.
Geoff Langa71a98e2017-06-19 15:15:00 -0400780bool IsValidESSLCharacter(unsigned char c, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400781{
782 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langa71a98e2017-06-19 15:15:00 -0400783 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' &&
784 (allowBackslash || c != '\\') && c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400785 {
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
Geoff Langa71a98e2017-06-19 15:15:00 -0400798bool IsValidESSLString(const char *str, size_t len, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400799{
Geoff Langa71a98e2017-06-19 15:15:00 -0400800 for (size_t i = 0; i < len; i++)
801 {
802 if (!IsValidESSLCharacter(str[i], allowBackslash))
803 {
804 return false;
805 }
806 }
807
808 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400809}
810
Jamie Madillc29968b2016-01-20 11:17:23 -0500811} // anonymous namespace
812
Geoff Langff5b2d52016-09-07 11:32:23 -0400813bool ValidateES2TexImageParameters(Context *context,
814 GLenum target,
815 GLint level,
816 GLenum internalformat,
817 bool isCompressed,
818 bool isSubImage,
819 GLint xoffset,
820 GLint yoffset,
821 GLsizei width,
822 GLsizei height,
823 GLint border,
824 GLenum format,
825 GLenum type,
826 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400827 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828{
Jamie Madill6f38f822014-06-06 17:12:20 -0400829 if (!ValidTexture2DDestinationTarget(context, target))
830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500831 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400832 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400833 }
834
Austin Kinross08528e12015-10-07 16:24:40 -0700835 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500837 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400838 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 }
840
He Yunchaoced53ae2016-11-29 15:00:51 +0800841 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 std::numeric_limits<GLsizei>::max() - yoffset < height)
843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500844 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400845 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 }
847
Geoff Lang6e898aa2017-06-02 11:17:26 -0400848 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
849 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
850 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
851 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
852 // case.
853 bool nonEqualFormatsAllowed =
854 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
855 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
856
857 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500859 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400860 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 }
862
Geoff Langaae65a42014-05-26 12:43:44 -0400863 const gl::Caps &caps = context->getCaps();
864
Geoff Langa9be0dc2014-12-17 12:34:40 -0500865 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500867 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
868 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
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 Langa9be0dc2014-12-17 12:34:40 -0500873 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500874 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500875 {
876 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500878 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500879 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400880 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400881
Geoff Langa9be0dc2014-12-17 12:34:40 -0500882 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
883 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500885 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500886 return false;
887 }
888 }
889 else
890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400892 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 }
894
He Yunchaoced53ae2016-11-29 15:00:51 +0800895 gl::Texture *texture =
896 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400897 if (!texture)
898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500899 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400900 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901 }
902
Geoff Langa9be0dc2014-12-17 12:34:40 -0500903 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400904 {
Geoff Langca271392017-04-05 12:30:00 -0400905 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
906 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500908 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500909 return false;
910 }
911
Geoff Langa9be0dc2014-12-17 12:34:40 -0500912 if (format != GL_NONE)
913 {
Geoff Langca271392017-04-05 12:30:00 -0400914 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
915 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500917 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500918 return false;
919 }
920 }
921
922 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
923 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500925 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500926 return false;
927 }
928 }
929 else
930 {
Geoff Lang69cce582015-09-17 13:20:36 -0400931 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500933 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500934 return false;
935 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400936 }
937
938 // Verify zero border
939 if (border != 0)
940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400942 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 }
944
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 if (isCompressed)
946 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400947 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400948 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
949 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 switch (actualInternalFormat)
951 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800952 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
953 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
954 if (!context->getExtensions().textureCompressionDXT1)
955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800957 return false;
958 }
959 break;
960 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
961 if (!context->getExtensions().textureCompressionDXT1)
962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500963 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800964 return false;
965 }
966 break;
967 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
968 if (!context->getExtensions().textureCompressionDXT5)
969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500970 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800971 return false;
972 }
973 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800974 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
975 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
976 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
977 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
978 if (!context->getExtensions().textureCompressionS3TCsRGB)
979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500980 context->handleError(InvalidEnum());
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800981 return false;
982 }
983 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800984 case GL_ETC1_RGB8_OES:
985 if (!context->getExtensions().compressedETC1RGB8Texture)
986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500987 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800988 return false;
989 }
990 break;
991 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800992 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
993 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
994 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
995 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 if (!context->getExtensions().lossyETCDecode)
997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500998 context->handleError(InvalidEnum()
999 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001000 return false;
1001 }
1002 break;
1003 default:
1004 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001005 InvalidEnum()
1006 << "internalformat is not a supported compressed internal format");
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001008 }
Geoff Lang966c9402017-04-18 12:38:27 -04001009
1010 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001011 {
Geoff Lang966c9402017-04-18 12:38:27 -04001012 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1013 height, texture->getWidth(target, level),
1014 texture->getHeight(target, level)))
1015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001016 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001017 return false;
1018 }
1019
1020 if (format != actualInternalFormat)
1021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001022 context->handleError(InvalidOperation()
1023 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -04001024 return false;
1025 }
1026 }
1027 else
1028 {
1029 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001031 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001032 return false;
1033 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034 }
1035 }
1036 else
1037 {
1038 // validate <type> by itself (used as secondary key below)
1039 switch (type)
1040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_UNSIGNED_BYTE:
1042 case GL_UNSIGNED_SHORT_5_6_5:
1043 case GL_UNSIGNED_SHORT_4_4_4_4:
1044 case GL_UNSIGNED_SHORT_5_5_5_1:
1045 case GL_UNSIGNED_SHORT:
1046 case GL_UNSIGNED_INT:
1047 case GL_UNSIGNED_INT_24_8_OES:
1048 case GL_HALF_FLOAT_OES:
1049 case GL_FLOAT:
1050 break;
1051 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001052 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001053 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001054 }
1055
1056 // validate <format> + <type> combinations
1057 // - invalid <format> -> sets INVALID_ENUM
1058 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1059 switch (format)
1060 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001061 case GL_ALPHA:
1062 case GL_LUMINANCE:
1063 case GL_LUMINANCE_ALPHA:
1064 switch (type)
1065 {
1066 case GL_UNSIGNED_BYTE:
1067 case GL_FLOAT:
1068 case GL_HALF_FLOAT_OES:
1069 break;
1070 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001071 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 return false;
1073 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 case GL_RED:
1076 case GL_RG:
1077 if (!context->getExtensions().textureRG)
1078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001079 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001080 return false;
1081 }
1082 switch (type)
1083 {
1084 case GL_UNSIGNED_BYTE:
1085 case GL_FLOAT:
1086 case GL_HALF_FLOAT_OES:
1087 break;
1088 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001089 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001090 return false;
1091 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001093 case GL_RGB:
1094 switch (type)
1095 {
1096 case GL_UNSIGNED_BYTE:
1097 case GL_UNSIGNED_SHORT_5_6_5:
1098 case GL_FLOAT:
1099 case GL_HALF_FLOAT_OES:
1100 break;
1101 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001102 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 return false;
1104 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 case GL_RGBA:
1107 switch (type)
1108 {
1109 case GL_UNSIGNED_BYTE:
1110 case GL_UNSIGNED_SHORT_4_4_4_4:
1111 case GL_UNSIGNED_SHORT_5_5_5_1:
1112 case GL_FLOAT:
1113 case GL_HALF_FLOAT_OES:
1114 break;
1115 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001116 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 return false;
1118 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 case GL_BGRA_EXT:
1121 switch (type)
1122 {
1123 case GL_UNSIGNED_BYTE:
1124 break;
1125 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001126 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 return false;
1128 }
1129 break;
1130 case GL_SRGB_EXT:
1131 case GL_SRGB_ALPHA_EXT:
1132 if (!context->getExtensions().sRGB)
1133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001135 return false;
1136 }
1137 switch (type)
1138 {
1139 case GL_UNSIGNED_BYTE:
1140 break;
1141 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001142 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001143 return false;
1144 }
1145 break;
1146 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1147 // handled below
1148 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1149 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1150 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1151 break;
1152 case GL_DEPTH_COMPONENT:
1153 switch (type)
1154 {
1155 case GL_UNSIGNED_SHORT:
1156 case GL_UNSIGNED_INT:
1157 break;
1158 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001159 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001160 return false;
1161 }
1162 break;
1163 case GL_DEPTH_STENCIL_OES:
1164 switch (type)
1165 {
1166 case GL_UNSIGNED_INT_24_8_OES:
1167 break;
1168 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001169 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001170 return false;
1171 }
1172 break;
1173 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001174 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001175 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 }
1177
1178 switch (format)
1179 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001180 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1181 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1182 if (context->getExtensions().textureCompressionDXT1)
1183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001184 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001185 return false;
1186 }
1187 else
1188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001189 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001190 return false;
1191 }
1192 break;
1193 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1194 if (context->getExtensions().textureCompressionDXT3)
1195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001196 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001197 return false;
1198 }
1199 else
1200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001201 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 return false;
1203 }
1204 break;
1205 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1206 if (context->getExtensions().textureCompressionDXT5)
1207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001208 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001209 return false;
1210 }
1211 else
1212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001213 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 return false;
1215 }
1216 break;
1217 case GL_ETC1_RGB8_OES:
1218 if (context->getExtensions().compressedETC1RGB8Texture)
1219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001220 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 return false;
1222 }
1223 else
1224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001225 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001226 return false;
1227 }
1228 break;
1229 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001230 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1231 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1232 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1233 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 if (context->getExtensions().lossyETCDecode)
1235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001236 context->handleError(InvalidOperation()
1237 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001238 return false;
1239 }
1240 else
1241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001242 context->handleError(InvalidEnum()
1243 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001244 return false;
1245 }
1246 break;
1247 case GL_DEPTH_COMPONENT:
1248 case GL_DEPTH_STENCIL_OES:
1249 if (!context->getExtensions().depthTextures)
1250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001251 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001252 return false;
1253 }
1254 if (target != GL_TEXTURE_2D)
1255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001256 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001257 return false;
1258 }
1259 // OES_depth_texture supports loading depth data and multiple levels,
1260 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001261 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001263 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001264 return false;
1265 }
1266 break;
1267 default:
1268 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 }
1270
Geoff Lang6e898aa2017-06-02 11:17:26 -04001271 if (!isSubImage)
1272 {
1273 switch (internalformat)
1274 {
1275 case GL_RGBA32F:
1276 if (!context->getExtensions().colorBufferFloatRGBA)
1277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001278 context->handleError(InvalidValue()
1279 << "Sized GL_RGBA32F internal format requires "
1280 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001281 return false;
1282 }
1283 if (type != GL_FLOAT)
1284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001285 context->handleError(InvalidOperation()
1286 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001287 return false;
1288 }
1289 if (format != GL_RGBA)
1290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001291 context->handleError(InvalidOperation()
1292 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001293 return false;
1294 }
1295 break;
1296
1297 case GL_RGB32F:
1298 if (!context->getExtensions().colorBufferFloatRGB)
1299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001300 context->handleError(InvalidValue()
1301 << "Sized GL_RGB32F internal format requires "
1302 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001303 return false;
1304 }
1305 if (type != GL_FLOAT)
1306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001307 context->handleError(InvalidOperation()
1308 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001309 return false;
1310 }
1311 if (format != GL_RGB)
1312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001313 context->handleError(InvalidOperation()
1314 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001315 return false;
1316 }
1317 break;
1318
1319 default:
1320 break;
1321 }
1322 }
1323
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 if (type == GL_FLOAT)
1325 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001326 if (!context->getExtensions().textureFloat)
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 else if (type == GL_HALF_FLOAT_OES)
1333 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001334 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 }
1339 }
1340 }
1341
Geoff Langdbcced82017-06-06 15:55:54 -04001342 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1343 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001344 imageSize))
1345 {
1346 return false;
1347 }
1348
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 return true;
1350}
1351
He Yunchaoced53ae2016-11-29 15:00:51 +08001352bool ValidateES2TexStorageParameters(Context *context,
1353 GLenum target,
1354 GLsizei levels,
1355 GLenum internalformat,
1356 GLsizei width,
1357 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358{
1359 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
1365 if (width < 1 || height < 1 || levels < 1)
1366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
1371 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 }
1376
1377 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 }
1382
Geoff Langca271392017-04-05 12:30:00 -04001383 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001384 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001386 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001387 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
1389
Geoff Langaae65a42014-05-26 12:43:44 -04001390 const gl::Caps &caps = context->getCaps();
1391
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 switch (target)
1393 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001394 case GL_TEXTURE_2D:
1395 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1396 static_cast<GLuint>(height) > caps.max2DTextureSize)
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 case GL_TEXTURE_CUBE_MAP:
1403 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1404 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001407 return false;
1408 }
1409 break;
1410 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001412 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 }
1414
Geoff Langc0b9ef42014-07-02 10:02:37 -04001415 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
1417 if (!gl::isPow2(width) || !gl::isPow2(height))
1418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001420 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 }
1422 }
1423
1424 switch (internalformat)
1425 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001426 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1427 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1428 if (!context->getExtensions().textureCompressionDXT1)
1429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001430 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001431 return false;
1432 }
1433 break;
1434 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1435 if (!context->getExtensions().textureCompressionDXT3)
1436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001437 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001438 return false;
1439 }
1440 break;
1441 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1442 if (!context->getExtensions().textureCompressionDXT5)
1443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001444 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001445 return false;
1446 }
1447 break;
1448 case GL_ETC1_RGB8_OES:
1449 if (!context->getExtensions().compressedETC1RGB8Texture)
1450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001451 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001452 return false;
1453 }
1454 break;
1455 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001456 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1457 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1458 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1459 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 if (!context->getExtensions().lossyETCDecode)
1461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001462 context->handleError(InvalidEnum()
1463 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001464 return false;
1465 }
1466 break;
1467 case GL_RGBA32F_EXT:
1468 case GL_RGB32F_EXT:
1469 case GL_ALPHA32F_EXT:
1470 case GL_LUMINANCE32F_EXT:
1471 case GL_LUMINANCE_ALPHA32F_EXT:
1472 if (!context->getExtensions().textureFloat)
1473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001474 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001475 return false;
1476 }
1477 break;
1478 case GL_RGBA16F_EXT:
1479 case GL_RGB16F_EXT:
1480 case GL_ALPHA16F_EXT:
1481 case GL_LUMINANCE16F_EXT:
1482 case GL_LUMINANCE_ALPHA16F_EXT:
1483 if (!context->getExtensions().textureHalfFloat)
1484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001485 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 return false;
1487 }
1488 break;
1489 case GL_R8_EXT:
1490 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001491 if (!context->getExtensions().textureRG)
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_R16F_EXT:
1498 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001499 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001501 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001502 return false;
1503 }
1504 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001505 case GL_R32F_EXT:
1506 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001507 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001509 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001510 return false;
1511 }
1512 break;
1513 case GL_DEPTH_COMPONENT16:
1514 case GL_DEPTH_COMPONENT32_OES:
1515 case GL_DEPTH24_STENCIL8_OES:
1516 if (!context->getExtensions().depthTextures)
1517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001518 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001519 return false;
1520 }
1521 if (target != GL_TEXTURE_2D)
1522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001524 return false;
1525 }
1526 // ANGLE_depth_texture only supports 1-level textures
1527 if (levels != 1)
1528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001530 return false;
1531 }
1532 break;
1533 default:
1534 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 }
1536
Geoff Lang691e58c2014-12-19 17:03:25 -05001537 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 if (!texture || texture->id() == 0)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001541 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001542 }
1543
Geoff Lang69cce582015-09-17 13:20:36 -04001544 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001546 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001547 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001548 }
1549
1550 return true;
1551}
1552
He Yunchaoced53ae2016-11-29 15:00:51 +08001553bool ValidateDiscardFramebufferEXT(Context *context,
1554 GLenum target,
1555 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001556 const GLenum *attachments)
1557{
Jamie Madillc29968b2016-01-20 11:17:23 -05001558 if (!context->getExtensions().discardFramebuffer)
1559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001560 context->handleError(InvalidOperation() << "Extension not enabled");
Jamie Madillc29968b2016-01-20 11:17:23 -05001561 return false;
1562 }
1563
Austin Kinross08332632015-05-05 13:35:47 -07001564 bool defaultFramebuffer = false;
1565
1566 switch (target)
1567 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001568 case GL_FRAMEBUFFER:
1569 defaultFramebuffer =
1570 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1571 break;
1572 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001573 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001574 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001575 }
1576
He Yunchaoced53ae2016-11-29 15:00:51 +08001577 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1578 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001579}
1580
Austin Kinrossbc781f32015-10-26 09:27:38 -07001581bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1582{
1583 if (!context->getExtensions().vertexArrayObject)
1584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001585 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001586 return false;
1587 }
1588
1589 return ValidateBindVertexArrayBase(context, array);
1590}
1591
1592bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1593{
1594 if (!context->getExtensions().vertexArrayObject)
1595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001596 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001597 return false;
1598 }
1599
Olli Etuaho41997e72016-03-10 13:38:39 +02001600 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001601}
1602
1603bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1604{
1605 if (!context->getExtensions().vertexArrayObject)
1606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001607 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001608 return false;
1609 }
1610
Olli Etuaho41997e72016-03-10 13:38:39 +02001611 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001612}
1613
1614bool ValidateIsVertexArrayOES(Context *context)
1615{
1616 if (!context->getExtensions().vertexArrayObject)
1617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001618 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001619 return false;
1620 }
1621
1622 return true;
1623}
Geoff Langc5629752015-12-07 16:29:04 -05001624
1625bool ValidateProgramBinaryOES(Context *context,
1626 GLuint program,
1627 GLenum binaryFormat,
1628 const void *binary,
1629 GLint length)
1630{
1631 if (!context->getExtensions().getProgramBinary)
1632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001633 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001634 return false;
1635 }
1636
1637 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1638}
1639
1640bool ValidateGetProgramBinaryOES(Context *context,
1641 GLuint program,
1642 GLsizei bufSize,
1643 GLsizei *length,
1644 GLenum *binaryFormat,
1645 void *binary)
1646{
1647 if (!context->getExtensions().getProgramBinary)
1648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001649 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001650 return false;
1651 }
1652
1653 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1654}
Geoff Lange102fee2015-12-10 11:23:30 -05001655
Geoff Lang70d0f492015-12-10 17:45:46 -05001656static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1657{
1658 switch (source)
1659 {
1660 case GL_DEBUG_SOURCE_API:
1661 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1662 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1663 case GL_DEBUG_SOURCE_OTHER:
1664 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1665 return !mustBeThirdPartyOrApplication;
1666
1667 case GL_DEBUG_SOURCE_THIRD_PARTY:
1668 case GL_DEBUG_SOURCE_APPLICATION:
1669 return true;
1670
1671 default:
1672 return false;
1673 }
1674}
1675
1676static bool ValidDebugType(GLenum type)
1677{
1678 switch (type)
1679 {
1680 case GL_DEBUG_TYPE_ERROR:
1681 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1682 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1683 case GL_DEBUG_TYPE_PERFORMANCE:
1684 case GL_DEBUG_TYPE_PORTABILITY:
1685 case GL_DEBUG_TYPE_OTHER:
1686 case GL_DEBUG_TYPE_MARKER:
1687 case GL_DEBUG_TYPE_PUSH_GROUP:
1688 case GL_DEBUG_TYPE_POP_GROUP:
1689 return true;
1690
1691 default:
1692 return false;
1693 }
1694}
1695
1696static bool ValidDebugSeverity(GLenum severity)
1697{
1698 switch (severity)
1699 {
1700 case GL_DEBUG_SEVERITY_HIGH:
1701 case GL_DEBUG_SEVERITY_MEDIUM:
1702 case GL_DEBUG_SEVERITY_LOW:
1703 case GL_DEBUG_SEVERITY_NOTIFICATION:
1704 return true;
1705
1706 default:
1707 return false;
1708 }
1709}
1710
Geoff Lange102fee2015-12-10 11:23:30 -05001711bool ValidateDebugMessageControlKHR(Context *context,
1712 GLenum source,
1713 GLenum type,
1714 GLenum severity,
1715 GLsizei count,
1716 const GLuint *ids,
1717 GLboolean enabled)
1718{
1719 if (!context->getExtensions().debug)
1720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001721 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001722 return false;
1723 }
1724
Geoff Lang70d0f492015-12-10 17:45:46 -05001725 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001727 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001728 return false;
1729 }
1730
1731 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001733 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001734 return false;
1735 }
1736
1737 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001739 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001740 return false;
1741 }
1742
1743 if (count > 0)
1744 {
1745 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001747 context->handleError(
1748 InvalidOperation()
1749 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001750 return false;
1751 }
1752
1753 if (severity != GL_DONT_CARE)
1754 {
Jamie Madill437fa652016-05-03 15:13:24 -04001755 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001756 InvalidOperation()
1757 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001758 return false;
1759 }
1760 }
1761
Geoff Lange102fee2015-12-10 11:23:30 -05001762 return true;
1763}
1764
1765bool ValidateDebugMessageInsertKHR(Context *context,
1766 GLenum source,
1767 GLenum type,
1768 GLuint id,
1769 GLenum severity,
1770 GLsizei length,
1771 const GLchar *buf)
1772{
1773 if (!context->getExtensions().debug)
1774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001775 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001776 return false;
1777 }
1778
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001779 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001780 {
1781 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1782 // not generate an error.
1783 return false;
1784 }
1785
1786 if (!ValidDebugSeverity(severity))
1787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001788 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001789 return false;
1790 }
1791
1792 if (!ValidDebugType(type))
1793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001794 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001795 return false;
1796 }
1797
1798 if (!ValidDebugSource(source, true))
1799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001800 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001801 return false;
1802 }
1803
1804 size_t messageLength = (length < 0) ? strlen(buf) : length;
1805 if (messageLength > context->getExtensions().maxDebugMessageLength)
1806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001807 context->handleError(InvalidValue()
1808 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001809 return false;
1810 }
1811
Geoff Lange102fee2015-12-10 11:23:30 -05001812 return true;
1813}
1814
1815bool ValidateDebugMessageCallbackKHR(Context *context,
1816 GLDEBUGPROCKHR callback,
1817 const void *userParam)
1818{
1819 if (!context->getExtensions().debug)
1820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001821 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001822 return false;
1823 }
1824
Geoff Lange102fee2015-12-10 11:23:30 -05001825 return true;
1826}
1827
1828bool ValidateGetDebugMessageLogKHR(Context *context,
1829 GLuint count,
1830 GLsizei bufSize,
1831 GLenum *sources,
1832 GLenum *types,
1833 GLuint *ids,
1834 GLenum *severities,
1835 GLsizei *lengths,
1836 GLchar *messageLog)
1837{
1838 if (!context->getExtensions().debug)
1839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001840 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001841 return false;
1842 }
1843
Geoff Lang70d0f492015-12-10 17:45:46 -05001844 if (bufSize < 0 && messageLog != nullptr)
1845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001846 context->handleError(InvalidValue()
1847 << "bufSize must be positive if messageLog is not null.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001848 return false;
1849 }
1850
Geoff Lange102fee2015-12-10 11:23:30 -05001851 return true;
1852}
1853
1854bool ValidatePushDebugGroupKHR(Context *context,
1855 GLenum source,
1856 GLuint id,
1857 GLsizei length,
1858 const GLchar *message)
1859{
1860 if (!context->getExtensions().debug)
1861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001862 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001863 return false;
1864 }
1865
Geoff Lang70d0f492015-12-10 17:45:46 -05001866 if (!ValidDebugSource(source, true))
1867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001868 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001869 return false;
1870 }
1871
1872 size_t messageLength = (length < 0) ? strlen(message) : length;
1873 if (messageLength > context->getExtensions().maxDebugMessageLength)
1874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001875 context->handleError(InvalidValue()
1876 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001877 return false;
1878 }
1879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001880 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001881 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001883 context
1884 ->handleError(StackOverflow()
1885 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001886 return false;
1887 }
1888
Geoff Lange102fee2015-12-10 11:23:30 -05001889 return true;
1890}
1891
1892bool ValidatePopDebugGroupKHR(Context *context)
1893{
1894 if (!context->getExtensions().debug)
1895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001896 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001897 return false;
1898 }
1899
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001900 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001901 if (currentStackSize <= 1)
1902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001903 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 return false;
1905 }
1906
1907 return true;
1908}
1909
1910static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1911{
1912 switch (identifier)
1913 {
1914 case GL_BUFFER:
1915 if (context->getBuffer(name) == nullptr)
1916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001917 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001918 return false;
1919 }
1920 return true;
1921
1922 case GL_SHADER:
1923 if (context->getShader(name) == nullptr)
1924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001925 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001926 return false;
1927 }
1928 return true;
1929
1930 case GL_PROGRAM:
1931 if (context->getProgram(name) == nullptr)
1932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001933 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001934 return false;
1935 }
1936 return true;
1937
1938 case GL_VERTEX_ARRAY:
1939 if (context->getVertexArray(name) == nullptr)
1940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001941 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001942 return false;
1943 }
1944 return true;
1945
1946 case GL_QUERY:
1947 if (context->getQuery(name) == nullptr)
1948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001949 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001950 return false;
1951 }
1952 return true;
1953
1954 case GL_TRANSFORM_FEEDBACK:
1955 if (context->getTransformFeedback(name) == nullptr)
1956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001957 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001958 return false;
1959 }
1960 return true;
1961
1962 case GL_SAMPLER:
1963 if (context->getSampler(name) == nullptr)
1964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001966 return false;
1967 }
1968 return true;
1969
1970 case GL_TEXTURE:
1971 if (context->getTexture(name) == nullptr)
1972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001973 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001974 return false;
1975 }
1976 return true;
1977
1978 case GL_RENDERBUFFER:
1979 if (context->getRenderbuffer(name) == nullptr)
1980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001981 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001982 return false;
1983 }
1984 return true;
1985
1986 case GL_FRAMEBUFFER:
1987 if (context->getFramebuffer(name) == nullptr)
1988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001989 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001990 return false;
1991 }
1992 return true;
1993
1994 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001995 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001996 return false;
1997 }
Geoff Lange102fee2015-12-10 11:23:30 -05001998}
1999
Martin Radev9d901792016-07-15 15:58:58 +03002000static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2001{
2002 size_t labelLength = 0;
2003
2004 if (length < 0)
2005 {
2006 if (label != nullptr)
2007 {
2008 labelLength = strlen(label);
2009 }
2010 }
2011 else
2012 {
2013 labelLength = static_cast<size_t>(length);
2014 }
2015
2016 if (labelLength > context->getExtensions().maxLabelLength)
2017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002018 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002019 return false;
2020 }
2021
2022 return true;
2023}
2024
Geoff Lange102fee2015-12-10 11:23:30 -05002025bool ValidateObjectLabelKHR(Context *context,
2026 GLenum identifier,
2027 GLuint name,
2028 GLsizei length,
2029 const GLchar *label)
2030{
2031 if (!context->getExtensions().debug)
2032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002033 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002034 return false;
2035 }
2036
Geoff Lang70d0f492015-12-10 17:45:46 -05002037 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2038 {
2039 return false;
2040 }
2041
Martin Radev9d901792016-07-15 15:58:58 +03002042 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002043 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002044 return false;
2045 }
2046
Geoff Lange102fee2015-12-10 11:23:30 -05002047 return true;
2048}
2049
2050bool ValidateGetObjectLabelKHR(Context *context,
2051 GLenum identifier,
2052 GLuint name,
2053 GLsizei bufSize,
2054 GLsizei *length,
2055 GLchar *label)
2056{
2057 if (!context->getExtensions().debug)
2058 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002059 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002060 return false;
2061 }
2062
Geoff Lang70d0f492015-12-10 17:45:46 -05002063 if (bufSize < 0)
2064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002065 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002066 return false;
2067 }
2068
2069 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2070 {
2071 return false;
2072 }
2073
Martin Radev9d901792016-07-15 15:58:58 +03002074 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002075}
2076
2077static bool ValidateObjectPtrName(Context *context, const void *ptr)
2078{
2079 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002081 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002082 return false;
2083 }
2084
Geoff Lange102fee2015-12-10 11:23:30 -05002085 return true;
2086}
2087
2088bool ValidateObjectPtrLabelKHR(Context *context,
2089 const void *ptr,
2090 GLsizei length,
2091 const GLchar *label)
2092{
2093 if (!context->getExtensions().debug)
2094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002095 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002096 return false;
2097 }
2098
Geoff Lang70d0f492015-12-10 17:45:46 -05002099 if (!ValidateObjectPtrName(context, ptr))
2100 {
2101 return false;
2102 }
2103
Martin Radev9d901792016-07-15 15:58:58 +03002104 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002105 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002106 return false;
2107 }
2108
Geoff Lange102fee2015-12-10 11:23:30 -05002109 return true;
2110}
2111
2112bool ValidateGetObjectPtrLabelKHR(Context *context,
2113 const void *ptr,
2114 GLsizei bufSize,
2115 GLsizei *length,
2116 GLchar *label)
2117{
2118 if (!context->getExtensions().debug)
2119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002120 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002121 return false;
2122 }
2123
Geoff Lang70d0f492015-12-10 17:45:46 -05002124 if (bufSize < 0)
2125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002126 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002127 return false;
2128 }
2129
2130 if (!ValidateObjectPtrName(context, ptr))
2131 {
2132 return false;
2133 }
2134
Martin Radev9d901792016-07-15 15:58:58 +03002135 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002136}
2137
2138bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2139{
2140 if (!context->getExtensions().debug)
2141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002142 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002143 return false;
2144 }
2145
Geoff Lang70d0f492015-12-10 17:45:46 -05002146 // TODO: represent this in Context::getQueryParameterInfo.
2147 switch (pname)
2148 {
2149 case GL_DEBUG_CALLBACK_FUNCTION:
2150 case GL_DEBUG_CALLBACK_USER_PARAM:
2151 break;
2152
2153 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002154 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002155 return false;
2156 }
2157
Geoff Lange102fee2015-12-10 11:23:30 -05002158 return true;
2159}
Jamie Madillc29968b2016-01-20 11:17:23 -05002160
2161bool ValidateBlitFramebufferANGLE(Context *context,
2162 GLint srcX0,
2163 GLint srcY0,
2164 GLint srcX1,
2165 GLint srcY1,
2166 GLint dstX0,
2167 GLint dstY0,
2168 GLint dstX1,
2169 GLint dstY1,
2170 GLbitfield mask,
2171 GLenum filter)
2172{
2173 if (!context->getExtensions().framebufferBlit)
2174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002175 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002176 return false;
2177 }
2178
2179 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2180 {
2181 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002182 context->handleError(InvalidOperation() << "Scaling and flipping in "
2183 "BlitFramebufferANGLE not supported by this "
2184 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002185 return false;
2186 }
2187
2188 if (filter == GL_LINEAR)
2189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002190 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002191 return false;
2192 }
2193
Jamie Madill51f40ec2016-06-15 14:06:00 -04002194 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2195 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002196
2197 if (mask & GL_COLOR_BUFFER_BIT)
2198 {
2199 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2200 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2201
2202 if (readColorAttachment && drawColorAttachment)
2203 {
2204 if (!(readColorAttachment->type() == GL_TEXTURE &&
2205 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2206 readColorAttachment->type() != GL_RENDERBUFFER &&
2207 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002210 return false;
2211 }
2212
Geoff Langa15472a2015-08-11 11:48:03 -04002213 for (size_t drawbufferIdx = 0;
2214 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002215 {
Geoff Langa15472a2015-08-11 11:48:03 -04002216 const FramebufferAttachment *attachment =
2217 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2218 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002219 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002220 if (!(attachment->type() == GL_TEXTURE &&
2221 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2222 attachment->type() != GL_RENDERBUFFER &&
2223 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002225 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002226 return false;
2227 }
2228
2229 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002230 if (!Format::SameSized(attachment->getFormat(),
2231 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002233 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002234 return false;
2235 }
2236 }
2237 }
2238
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002239 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002240 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2241 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002243 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002244 return false;
2245 }
2246 }
2247 }
2248
2249 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2250 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2251 for (size_t i = 0; i < 2; i++)
2252 {
2253 if (mask & masks[i])
2254 {
2255 const FramebufferAttachment *readBuffer =
2256 readFramebuffer->getAttachment(attachments[i]);
2257 const FramebufferAttachment *drawBuffer =
2258 drawFramebuffer->getAttachment(attachments[i]);
2259
2260 if (readBuffer && drawBuffer)
2261 {
2262 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2263 dstX0, dstY0, dstX1, dstY1))
2264 {
2265 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002266 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2267 "stencil blits are supported by "
2268 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002269 return false;
2270 }
2271
2272 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002275 return false;
2276 }
2277 }
2278 }
2279 }
2280
2281 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2282 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002283}
Jamie Madillc29968b2016-01-20 11:17:23 -05002284
2285bool ValidateClear(ValidationContext *context, GLbitfield mask)
2286{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002287 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002288 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002290 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002291 return false;
2292 }
2293
2294 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002296 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05002297 return false;
2298 }
2299
Geoff Lang76e65652017-03-27 14:58:02 -04002300 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2301 {
2302 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2303 GL_SIGNED_NORMALIZED};
2304
2305 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2306 drawBufferIdx++)
2307 {
2308 if (!ValidateWebGLFramebufferAttachmentClearType(
2309 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2310 {
2311 return false;
2312 }
2313 }
2314 }
2315
Jamie Madillc29968b2016-01-20 11:17:23 -05002316 return true;
2317}
2318
2319bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2320{
2321 if (!context->getExtensions().drawBuffers)
2322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002323 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002324 return false;
2325 }
2326
2327 return ValidateDrawBuffersBase(context, n, bufs);
2328}
2329
Jamie Madill73a84962016-02-12 09:27:23 -05002330bool ValidateTexImage2D(Context *context,
2331 GLenum target,
2332 GLint level,
2333 GLint internalformat,
2334 GLsizei width,
2335 GLsizei height,
2336 GLint border,
2337 GLenum format,
2338 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002339 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002340{
Martin Radev1be913c2016-07-11 17:59:16 +03002341 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002342 {
2343 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002344 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002345 }
2346
Martin Radev1be913c2016-07-11 17:59:16 +03002347 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002348 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002349 0, 0, width, height, 1, border, format, type, -1,
2350 pixels);
2351}
2352
2353bool ValidateTexImage2DRobust(Context *context,
2354 GLenum target,
2355 GLint level,
2356 GLint internalformat,
2357 GLsizei width,
2358 GLsizei height,
2359 GLint border,
2360 GLenum format,
2361 GLenum type,
2362 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002363 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002364{
2365 if (!ValidateRobustEntryPoint(context, bufSize))
2366 {
2367 return false;
2368 }
2369
2370 if (context->getClientMajorVersion() < 3)
2371 {
2372 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2373 0, 0, width, height, border, format, type, bufSize,
2374 pixels);
2375 }
2376
2377 ASSERT(context->getClientMajorVersion() >= 3);
2378 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2379 0, 0, width, height, 1, border, format, type, bufSize,
2380 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002381}
2382
2383bool ValidateTexSubImage2D(Context *context,
2384 GLenum target,
2385 GLint level,
2386 GLint xoffset,
2387 GLint yoffset,
2388 GLsizei width,
2389 GLsizei height,
2390 GLenum format,
2391 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002392 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002393{
2394
Martin Radev1be913c2016-07-11 17:59:16 +03002395 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002396 {
2397 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002398 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002399 }
2400
Martin Radev1be913c2016-07-11 17:59:16 +03002401 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002402 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002403 yoffset, 0, width, height, 1, 0, format, type, -1,
2404 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002405}
2406
Geoff Langc52f6f12016-10-14 10:18:00 -04002407bool ValidateTexSubImage2DRobustANGLE(Context *context,
2408 GLenum target,
2409 GLint level,
2410 GLint xoffset,
2411 GLint yoffset,
2412 GLsizei width,
2413 GLsizei height,
2414 GLenum format,
2415 GLenum type,
2416 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002417 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002418{
2419 if (!ValidateRobustEntryPoint(context, bufSize))
2420 {
2421 return false;
2422 }
2423
2424 if (context->getClientMajorVersion() < 3)
2425 {
2426 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2427 yoffset, width, height, 0, format, type, bufSize,
2428 pixels);
2429 }
2430
2431 ASSERT(context->getClientMajorVersion() >= 3);
2432 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2433 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2434 pixels);
2435}
2436
Jamie Madill73a84962016-02-12 09:27:23 -05002437bool ValidateCompressedTexImage2D(Context *context,
2438 GLenum target,
2439 GLint level,
2440 GLenum internalformat,
2441 GLsizei width,
2442 GLsizei height,
2443 GLint border,
2444 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002445 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002446{
Martin Radev1be913c2016-07-11 17:59:16 +03002447 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002448 {
2449 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002450 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002451 {
2452 return false;
2453 }
2454 }
2455 else
2456 {
Martin Radev1be913c2016-07-11 17:59:16 +03002457 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002458 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002459 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002460 data))
2461 {
2462 return false;
2463 }
2464 }
2465
Geoff Langca271392017-04-05 12:30:00 -04002466 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002467 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002468 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002469 if (blockSizeOrErr.isError())
2470 {
2471 context->handleError(blockSizeOrErr.getError());
2472 return false;
2473 }
2474
2475 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002477 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002478 return false;
2479 }
2480
2481 return true;
2482}
2483
Corentin Wallezb2931602017-04-11 15:58:57 -04002484bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2485 GLenum target,
2486 GLint level,
2487 GLenum internalformat,
2488 GLsizei width,
2489 GLsizei height,
2490 GLint border,
2491 GLsizei imageSize,
2492 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002493 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002494{
2495 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2496 {
2497 return false;
2498 }
2499
2500 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2501 border, imageSize, data);
2502}
2503bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2504 GLenum target,
2505 GLint level,
2506 GLint xoffset,
2507 GLint yoffset,
2508 GLsizei width,
2509 GLsizei height,
2510 GLenum format,
2511 GLsizei imageSize,
2512 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002513 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002514{
2515 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2516 {
2517 return false;
2518 }
2519
2520 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2521 format, imageSize, data);
2522}
2523
Jamie Madill73a84962016-02-12 09:27:23 -05002524bool ValidateCompressedTexSubImage2D(Context *context,
2525 GLenum target,
2526 GLint level,
2527 GLint xoffset,
2528 GLint yoffset,
2529 GLsizei width,
2530 GLsizei height,
2531 GLenum format,
2532 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002533 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002534{
Martin Radev1be913c2016-07-11 17:59:16 +03002535 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002536 {
2537 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002538 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002539 {
2540 return false;
2541 }
2542 }
2543 else
2544 {
Martin Radev1be913c2016-07-11 17:59:16 +03002545 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002546 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002547 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002548 data))
2549 {
2550 return false;
2551 }
2552 }
2553
Geoff Langca271392017-04-05 12:30:00 -04002554 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002555 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002556 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002557 if (blockSizeOrErr.isError())
2558 {
2559 context->handleError(blockSizeOrErr.getError());
2560 return false;
2561 }
2562
2563 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002566 return false;
2567 }
2568
2569 return true;
2570}
2571
Olli Etuaho4f667482016-03-30 15:56:35 +03002572bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2573{
Geoff Lang496c02d2016-10-20 11:38:11 -07002574 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002575}
2576
2577bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2578{
2579 if (!context->getExtensions().mapBuffer)
2580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002581 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002582 return false;
2583 }
2584
2585 if (!ValidBufferTarget(context, target))
2586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002587 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002588 return false;
2589 }
2590
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002591 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002592
2593 if (buffer == nullptr)
2594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002595 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002596 return false;
2597 }
2598
2599 if (access != GL_WRITE_ONLY_OES)
2600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002601 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002602 return false;
2603 }
2604
2605 if (buffer->isMapped())
2606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002607 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002608 return false;
2609 }
2610
2611 return true;
2612}
2613
2614bool ValidateUnmapBufferOES(Context *context, GLenum target)
2615{
2616 if (!context->getExtensions().mapBuffer)
2617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002618 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002619 return false;
2620 }
2621
2622 return ValidateUnmapBufferBase(context, target);
2623}
2624
2625bool ValidateMapBufferRangeEXT(Context *context,
2626 GLenum target,
2627 GLintptr offset,
2628 GLsizeiptr length,
2629 GLbitfield access)
2630{
2631 if (!context->getExtensions().mapBufferRange)
2632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002633 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002634 return false;
2635 }
2636
2637 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2638}
2639
2640bool ValidateFlushMappedBufferRangeEXT(Context *context,
2641 GLenum target,
2642 GLintptr offset,
2643 GLsizeiptr length)
2644{
2645 if (!context->getExtensions().mapBufferRange)
2646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002647 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002648 return false;
2649 }
2650
2651 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2652}
2653
Ian Ewell54f87462016-03-10 13:47:21 -05002654bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2655{
2656 Texture *textureObject = context->getTexture(texture);
2657 if (textureObject && textureObject->getTarget() != target && texture != 0)
2658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002659 context->handleError(InvalidOperation() << "Invalid texture");
Ian Ewell54f87462016-03-10 13:47:21 -05002660 return false;
2661 }
2662
Geoff Langf41a7152016-09-19 15:11:17 -04002663 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2664 !context->isTextureGenerated(texture))
2665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002666 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002667 return false;
2668 }
2669
Ian Ewell54f87462016-03-10 13:47:21 -05002670 switch (target)
2671 {
2672 case GL_TEXTURE_2D:
2673 case GL_TEXTURE_CUBE_MAP:
2674 break;
2675
2676 case GL_TEXTURE_3D:
2677 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002678 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002680 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002681 return false;
2682 }
2683 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002684
2685 case GL_TEXTURE_2D_MULTISAMPLE:
2686 if (context->getClientVersion() < Version(3, 1))
2687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002688 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002689 return false;
2690 }
Geoff Lang3b573612016-10-31 14:08:10 -04002691 break;
2692
Ian Ewell54f87462016-03-10 13:47:21 -05002693 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002694 if (!context->getExtensions().eglImageExternal &&
2695 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002697 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002698 return false;
2699 }
2700 break;
2701 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002702 context->handleError(InvalidEnum() << "Invalid target");
Ian Ewell54f87462016-03-10 13:47:21 -05002703 return false;
2704 }
2705
2706 return true;
2707}
2708
Geoff Langd8605522016-04-13 10:19:12 -04002709bool ValidateBindUniformLocationCHROMIUM(Context *context,
2710 GLuint program,
2711 GLint location,
2712 const GLchar *name)
2713{
2714 if (!context->getExtensions().bindUniformLocation)
2715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002716 context->handleError(InvalidOperation()
2717 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002718 return false;
2719 }
2720
2721 Program *programObject = GetValidProgram(context, program);
2722 if (!programObject)
2723 {
2724 return false;
2725 }
2726
2727 if (location < 0)
2728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002729 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002730 return false;
2731 }
2732
2733 const Caps &caps = context->getCaps();
2734 if (static_cast<size_t>(location) >=
2735 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002737 context->handleError(InvalidValue() << "Location must be less than "
2738 "(MAX_VERTEX_UNIFORM_VECTORS + "
2739 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002740 return false;
2741 }
2742
Geoff Langfc32e8b2017-05-31 14:16:59 -04002743 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2744 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04002745 if (context->getExtensions().webglCompatibility &&
2746 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002748 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04002749 return false;
2750 }
2751
Geoff Langd8605522016-04-13 10:19:12 -04002752 if (strncmp(name, "gl_", 3) == 0)
2753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002754 context->handleError(InvalidOperation()
2755 << "Name cannot start with the reserved \"gl_\" prefix.");
Geoff Langd8605522016-04-13 10:19:12 -04002756 return false;
2757 }
2758
2759 return true;
2760}
2761
Jamie Madille2e406c2016-06-02 13:04:10 -04002762bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002763{
2764 if (!context->getExtensions().framebufferMixedSamples)
2765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002766 context->handleError(InvalidOperation()
2767 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002768 return false;
2769 }
2770 switch (components)
2771 {
2772 case GL_RGB:
2773 case GL_RGBA:
2774 case GL_ALPHA:
2775 case GL_NONE:
2776 break;
2777 default:
2778 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002779 InvalidEnum()
2780 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002781 return false;
2782 }
2783
2784 return true;
2785}
2786
Sami Väisänene45e53b2016-05-25 10:36:04 +03002787// CHROMIUM_path_rendering
2788
2789bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2790{
2791 if (!context->getExtensions().pathRendering)
2792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002793 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002794 return false;
2795 }
2796 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002798 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002799 return false;
2800 }
2801 if (matrix == nullptr)
2802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002803 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002804 return false;
2805 }
2806 return true;
2807}
2808
2809bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2810{
2811 if (!context->getExtensions().pathRendering)
2812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002813 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002814 return false;
2815 }
2816 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002818 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002819 return false;
2820 }
2821 return true;
2822}
2823
2824bool ValidateGenPaths(Context *context, GLsizei range)
2825{
2826 if (!context->getExtensions().pathRendering)
2827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002828 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002829 return false;
2830 }
2831
2832 // range = 0 is undefined in NV_path_rendering.
2833 // we add stricter semantic check here and require a non zero positive range.
2834 if (range <= 0)
2835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002836 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002837 return false;
2838 }
2839
2840 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002842 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002843 return false;
2844 }
2845
2846 return true;
2847}
2848
2849bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2850{
2851 if (!context->getExtensions().pathRendering)
2852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002853 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002854 return false;
2855 }
2856
2857 // range = 0 is undefined in NV_path_rendering.
2858 // we add stricter semantic check here and require a non zero positive range.
2859 if (range <= 0)
2860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002861 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002862 return false;
2863 }
2864
2865 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2866 checkedRange += range;
2867
2868 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002870 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002871 return false;
2872 }
2873 return true;
2874}
2875
2876bool ValidatePathCommands(Context *context,
2877 GLuint path,
2878 GLsizei numCommands,
2879 const GLubyte *commands,
2880 GLsizei numCoords,
2881 GLenum coordType,
2882 const void *coords)
2883{
2884 if (!context->getExtensions().pathRendering)
2885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002886 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002887 return false;
2888 }
2889 if (!context->hasPath(path))
2890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002891 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002892 return false;
2893 }
2894
2895 if (numCommands < 0)
2896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002897 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002898 return false;
2899 }
2900 else if (numCommands > 0)
2901 {
2902 if (!commands)
2903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002904 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002905 return false;
2906 }
2907 }
2908
2909 if (numCoords < 0)
2910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002911 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002912 return false;
2913 }
2914 else if (numCoords > 0)
2915 {
2916 if (!coords)
2917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002918 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002919 return false;
2920 }
2921 }
2922
2923 std::uint32_t coordTypeSize = 0;
2924 switch (coordType)
2925 {
2926 case GL_BYTE:
2927 coordTypeSize = sizeof(GLbyte);
2928 break;
2929
2930 case GL_UNSIGNED_BYTE:
2931 coordTypeSize = sizeof(GLubyte);
2932 break;
2933
2934 case GL_SHORT:
2935 coordTypeSize = sizeof(GLshort);
2936 break;
2937
2938 case GL_UNSIGNED_SHORT:
2939 coordTypeSize = sizeof(GLushort);
2940 break;
2941
2942 case GL_FLOAT:
2943 coordTypeSize = sizeof(GLfloat);
2944 break;
2945
2946 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002947 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002948 return false;
2949 }
2950
2951 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2952 checkedSize += (coordTypeSize * numCoords);
2953 if (!checkedSize.IsValid())
2954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002955 context->handleError(InvalidOperation() << "Coord size overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002956 return false;
2957 }
2958
2959 // early return skips command data validation when it doesn't exist.
2960 if (!commands)
2961 return true;
2962
2963 GLsizei expectedNumCoords = 0;
2964 for (GLsizei i = 0; i < numCommands; ++i)
2965 {
2966 switch (commands[i])
2967 {
2968 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2969 break;
2970 case GL_MOVE_TO_CHROMIUM:
2971 case GL_LINE_TO_CHROMIUM:
2972 expectedNumCoords += 2;
2973 break;
2974 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2975 expectedNumCoords += 4;
2976 break;
2977 case GL_CUBIC_CURVE_TO_CHROMIUM:
2978 expectedNumCoords += 6;
2979 break;
2980 case GL_CONIC_CURVE_TO_CHROMIUM:
2981 expectedNumCoords += 5;
2982 break;
2983 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002984 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002985 return false;
2986 }
2987 }
2988 if (expectedNumCoords != numCoords)
2989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002990 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002991 return false;
2992 }
2993
2994 return true;
2995}
2996
2997bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2998{
2999 if (!context->getExtensions().pathRendering)
3000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003001 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003002 return false;
3003 }
3004 if (!context->hasPath(path))
3005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003006 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003007 return false;
3008 }
3009
3010 switch (pname)
3011 {
3012 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3013 if (value < 0.0f)
3014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003015 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003016 return false;
3017 }
3018 break;
3019 case GL_PATH_END_CAPS_CHROMIUM:
3020 switch (static_cast<GLenum>(value))
3021 {
3022 case GL_FLAT_CHROMIUM:
3023 case GL_SQUARE_CHROMIUM:
3024 case GL_ROUND_CHROMIUM:
3025 break;
3026 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003027 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003028 return false;
3029 }
3030 break;
3031 case GL_PATH_JOIN_STYLE_CHROMIUM:
3032 switch (static_cast<GLenum>(value))
3033 {
3034 case GL_MITER_REVERT_CHROMIUM:
3035 case GL_BEVEL_CHROMIUM:
3036 case GL_ROUND_CHROMIUM:
3037 break;
3038 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003039 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003040 return false;
3041 }
3042 case GL_PATH_MITER_LIMIT_CHROMIUM:
3043 if (value < 0.0f)
3044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003045 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003046 return false;
3047 }
3048 break;
3049
3050 case GL_PATH_STROKE_BOUND_CHROMIUM:
3051 // no errors, only clamping.
3052 break;
3053
3054 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003055 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003056 return false;
3057 }
3058 return true;
3059}
3060
3061bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3062{
3063 if (!context->getExtensions().pathRendering)
3064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003065 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003066 return false;
3067 }
3068
3069 if (!context->hasPath(path))
3070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003071 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003072 return false;
3073 }
3074 if (!value)
3075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003076 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003077 return false;
3078 }
3079
3080 switch (pname)
3081 {
3082 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3083 case GL_PATH_END_CAPS_CHROMIUM:
3084 case GL_PATH_JOIN_STYLE_CHROMIUM:
3085 case GL_PATH_MITER_LIMIT_CHROMIUM:
3086 case GL_PATH_STROKE_BOUND_CHROMIUM:
3087 break;
3088
3089 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003090 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003091 return false;
3092 }
3093
3094 return true;
3095}
3096
3097bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3098{
3099 if (!context->getExtensions().pathRendering)
3100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003101 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003102 return false;
3103 }
3104
3105 switch (func)
3106 {
3107 case GL_NEVER:
3108 case GL_ALWAYS:
3109 case GL_LESS:
3110 case GL_LEQUAL:
3111 case GL_EQUAL:
3112 case GL_GEQUAL:
3113 case GL_GREATER:
3114 case GL_NOTEQUAL:
3115 break;
3116 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003117 context->handleError(InvalidEnum() << "Invalid stencil function.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003118 return false;
3119 }
3120
3121 return true;
3122}
3123
3124// Note that the spec specifies that for the path drawing commands
3125// if the path object is not an existing path object the command
3126// does nothing and no error is generated.
3127// However if the path object exists but has not been specified any
3128// commands then an error is generated.
3129
3130bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3131{
3132 if (!context->getExtensions().pathRendering)
3133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003134 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003135 return false;
3136 }
3137 if (context->hasPath(path) && !context->hasPathData(path))
3138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003139 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003140 return false;
3141 }
3142
3143 switch (fillMode)
3144 {
3145 case GL_COUNT_UP_CHROMIUM:
3146 case GL_COUNT_DOWN_CHROMIUM:
3147 break;
3148 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003149 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003150 return false;
3151 }
3152
3153 if (!isPow2(mask + 1))
3154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003155 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003156 return false;
3157 }
3158
3159 return true;
3160}
3161
3162bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3163{
3164 if (!context->getExtensions().pathRendering)
3165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003166 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003167 return false;
3168 }
3169 if (context->hasPath(path) && !context->hasPathData(path))
3170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003171 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003172 return false;
3173 }
3174
3175 return true;
3176}
3177
3178bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3179{
3180 if (!context->getExtensions().pathRendering)
3181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003182 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003183 return false;
3184 }
3185 if (context->hasPath(path) && !context->hasPathData(path))
3186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003187 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003188 return false;
3189 }
3190
3191 switch (coverMode)
3192 {
3193 case GL_CONVEX_HULL_CHROMIUM:
3194 case GL_BOUNDING_BOX_CHROMIUM:
3195 break;
3196 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003197 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003198 return false;
3199 }
3200 return true;
3201}
3202
3203bool ValidateStencilThenCoverFillPath(Context *context,
3204 GLuint path,
3205 GLenum fillMode,
3206 GLuint mask,
3207 GLenum coverMode)
3208{
3209 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3210 ValidateCoverPath(context, path, coverMode);
3211}
3212
3213bool ValidateStencilThenCoverStrokePath(Context *context,
3214 GLuint path,
3215 GLint reference,
3216 GLuint mask,
3217 GLenum coverMode)
3218{
3219 return ValidateStencilStrokePath(context, path, reference, mask) &&
3220 ValidateCoverPath(context, path, coverMode);
3221}
3222
3223bool ValidateIsPath(Context *context)
3224{
3225 if (!context->getExtensions().pathRendering)
3226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003227 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003228 return false;
3229 }
3230 return true;
3231}
3232
Sami Väisänend59ca052016-06-21 16:10:00 +03003233bool ValidateCoverFillPathInstanced(Context *context,
3234 GLsizei numPaths,
3235 GLenum pathNameType,
3236 const void *paths,
3237 GLuint pathBase,
3238 GLenum coverMode,
3239 GLenum transformType,
3240 const GLfloat *transformValues)
3241{
3242 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3243 transformType, transformValues))
3244 return false;
3245
3246 switch (coverMode)
3247 {
3248 case GL_CONVEX_HULL_CHROMIUM:
3249 case GL_BOUNDING_BOX_CHROMIUM:
3250 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3251 break;
3252 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003253 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003254 return false;
3255 }
3256
3257 return true;
3258}
3259
3260bool ValidateCoverStrokePathInstanced(Context *context,
3261 GLsizei numPaths,
3262 GLenum pathNameType,
3263 const void *paths,
3264 GLuint pathBase,
3265 GLenum coverMode,
3266 GLenum transformType,
3267 const GLfloat *transformValues)
3268{
3269 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3270 transformType, transformValues))
3271 return false;
3272
3273 switch (coverMode)
3274 {
3275 case GL_CONVEX_HULL_CHROMIUM:
3276 case GL_BOUNDING_BOX_CHROMIUM:
3277 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3278 break;
3279 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003280 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003281 return false;
3282 }
3283
3284 return true;
3285}
3286
3287bool ValidateStencilFillPathInstanced(Context *context,
3288 GLsizei numPaths,
3289 GLenum pathNameType,
3290 const void *paths,
3291 GLuint pathBase,
3292 GLenum fillMode,
3293 GLuint mask,
3294 GLenum transformType,
3295 const GLfloat *transformValues)
3296{
3297
3298 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3299 transformType, transformValues))
3300 return false;
3301
3302 switch (fillMode)
3303 {
3304 case GL_COUNT_UP_CHROMIUM:
3305 case GL_COUNT_DOWN_CHROMIUM:
3306 break;
3307 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003308 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003309 return false;
3310 }
3311 if (!isPow2(mask + 1))
3312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003313 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003314 return false;
3315 }
3316 return true;
3317}
3318
3319bool ValidateStencilStrokePathInstanced(Context *context,
3320 GLsizei numPaths,
3321 GLenum pathNameType,
3322 const void *paths,
3323 GLuint pathBase,
3324 GLint reference,
3325 GLuint mask,
3326 GLenum transformType,
3327 const GLfloat *transformValues)
3328{
3329 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3330 transformType, transformValues))
3331 return false;
3332
3333 // no more validation here.
3334
3335 return true;
3336}
3337
3338bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3339 GLsizei numPaths,
3340 GLenum pathNameType,
3341 const void *paths,
3342 GLuint pathBase,
3343 GLenum fillMode,
3344 GLuint mask,
3345 GLenum coverMode,
3346 GLenum transformType,
3347 const GLfloat *transformValues)
3348{
3349 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3350 transformType, transformValues))
3351 return false;
3352
3353 switch (coverMode)
3354 {
3355 case GL_CONVEX_HULL_CHROMIUM:
3356 case GL_BOUNDING_BOX_CHROMIUM:
3357 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3358 break;
3359 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003360 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003361 return false;
3362 }
3363
3364 switch (fillMode)
3365 {
3366 case GL_COUNT_UP_CHROMIUM:
3367 case GL_COUNT_DOWN_CHROMIUM:
3368 break;
3369 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003370 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003371 return false;
3372 }
3373 if (!isPow2(mask + 1))
3374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003375 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003376 return false;
3377 }
3378
3379 return true;
3380}
3381
3382bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3383 GLsizei numPaths,
3384 GLenum pathNameType,
3385 const void *paths,
3386 GLuint pathBase,
3387 GLint reference,
3388 GLuint mask,
3389 GLenum coverMode,
3390 GLenum transformType,
3391 const GLfloat *transformValues)
3392{
3393 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3394 transformType, transformValues))
3395 return false;
3396
3397 switch (coverMode)
3398 {
3399 case GL_CONVEX_HULL_CHROMIUM:
3400 case GL_BOUNDING_BOX_CHROMIUM:
3401 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3402 break;
3403 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003404 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003405 return false;
3406 }
3407
3408 return true;
3409}
3410
Sami Väisänen46eaa942016-06-29 10:26:37 +03003411bool ValidateBindFragmentInputLocation(Context *context,
3412 GLuint program,
3413 GLint location,
3414 const GLchar *name)
3415{
3416 if (!context->getExtensions().pathRendering)
3417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003418 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003419 return false;
3420 }
3421
3422 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3423 if (location >= MaxLocation)
3424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003425 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003426 return false;
3427 }
3428
3429 const auto *programObject = context->getProgram(program);
3430 if (!programObject)
3431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003432 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003433 return false;
3434 }
3435
3436 if (!name)
3437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003438 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003439 return false;
3440 }
3441
3442 if (angle::BeginsWith(name, "gl_"))
3443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003444 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003445 return false;
3446 }
3447
3448 return true;
3449}
3450
3451bool ValidateProgramPathFragmentInputGen(Context *context,
3452 GLuint program,
3453 GLint location,
3454 GLenum genMode,
3455 GLint components,
3456 const GLfloat *coeffs)
3457{
3458 if (!context->getExtensions().pathRendering)
3459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003460 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003461 return false;
3462 }
3463
3464 const auto *programObject = context->getProgram(program);
3465 if (!programObject || programObject->isFlaggedForDeletion())
3466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003467 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003468 return false;
3469 }
3470
3471 if (!programObject->isLinked())
3472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003473 context->handleError(InvalidOperation() << "Program is not linked.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003474 return false;
3475 }
3476
3477 switch (genMode)
3478 {
3479 case GL_NONE:
3480 if (components != 0)
3481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003483 return false;
3484 }
3485 break;
3486
3487 case GL_OBJECT_LINEAR_CHROMIUM:
3488 case GL_EYE_LINEAR_CHROMIUM:
3489 case GL_CONSTANT_CHROMIUM:
3490 if (components < 1 || components > 4)
3491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003492 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003493 return false;
3494 }
3495 if (!coeffs)
3496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003497 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003498 return false;
3499 }
3500 break;
3501
3502 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003503 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003504 return false;
3505 }
3506
3507 // If the location is -1 then the command is silently ignored
3508 // and no further validation is needed.
3509 if (location == -1)
3510 return true;
3511
Jamie Madillbd044ed2017-06-05 12:59:21 -04003512 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003513
3514 if (!binding.valid)
3515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003516 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003517 return false;
3518 }
3519
3520 if (binding.type != GL_NONE)
3521 {
3522 GLint expectedComponents = 0;
3523 switch (binding.type)
3524 {
3525 case GL_FLOAT:
3526 expectedComponents = 1;
3527 break;
3528 case GL_FLOAT_VEC2:
3529 expectedComponents = 2;
3530 break;
3531 case GL_FLOAT_VEC3:
3532 expectedComponents = 3;
3533 break;
3534 case GL_FLOAT_VEC4:
3535 expectedComponents = 4;
3536 break;
3537 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003538 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003539 InvalidOperation()
3540 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003541 return false;
3542 }
3543 if (expectedComponents != components && genMode != GL_NONE)
3544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003545 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003546 return false;
3547 }
3548 }
3549 return true;
3550}
3551
Geoff Lang97073d12016-04-20 10:42:34 -07003552bool ValidateCopyTextureCHROMIUM(Context *context,
3553 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003554 GLint sourceLevel,
3555 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003556 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003557 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003558 GLint internalFormat,
3559 GLenum destType,
3560 GLboolean unpackFlipY,
3561 GLboolean unpackPremultiplyAlpha,
3562 GLboolean unpackUnmultiplyAlpha)
3563{
3564 if (!context->getExtensions().copyTexture)
3565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003566 context->handleError(InvalidOperation()
3567 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003568 return false;
3569 }
3570
Geoff Lang4f0e0032017-05-01 16:04:35 -04003571 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003572 if (source == nullptr)
3573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003575 return false;
3576 }
3577
3578 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003580 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003581 return false;
3582 }
3583
3584 GLenum sourceTarget = source->getTarget();
3585 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003586
3587 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003589 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003590 return false;
3591 }
3592
Geoff Lang4f0e0032017-05-01 16:04:35 -04003593 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3594 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3595 if (sourceWidth == 0 || sourceHeight == 0)
3596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003597 context->handleError(InvalidValue()
3598 << "The source level of the source texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003599 return false;
3600 }
3601
3602 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3603 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003605 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003606 return false;
3607 }
3608
Geoff Lang4f0e0032017-05-01 16:04:35 -04003609 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003610 if (dest == nullptr)
3611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003612 context->handleError(InvalidValue()
3613 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003614 return false;
3615 }
3616
Geoff Lang4f0e0032017-05-01 16:04:35 -04003617 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003619 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003620 return false;
3621 }
3622
Geoff Lang4f0e0032017-05-01 16:04:35 -04003623 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3624 sourceHeight))
3625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003626 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003627 return false;
3628 }
3629
Geoff Lang97073d12016-04-20 10:42:34 -07003630 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003632 context->handleError(InvalidOperation()
3633 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003634 return false;
3635 }
3636
Geoff Lang4f0e0032017-05-01 16:04:35 -04003637 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(
3640 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003641 return false;
3642 }
3643
Geoff Lang97073d12016-04-20 10:42:34 -07003644 if (dest->getImmutableFormat())
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003647 return false;
3648 }
3649
3650 return true;
3651}
3652
3653bool ValidateCopySubTextureCHROMIUM(Context *context,
3654 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003655 GLint sourceLevel,
3656 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003657 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003658 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003659 GLint xoffset,
3660 GLint yoffset,
3661 GLint x,
3662 GLint y,
3663 GLsizei width,
3664 GLsizei height,
3665 GLboolean unpackFlipY,
3666 GLboolean unpackPremultiplyAlpha,
3667 GLboolean unpackUnmultiplyAlpha)
3668{
3669 if (!context->getExtensions().copyTexture)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003673 return false;
3674 }
3675
Geoff Lang4f0e0032017-05-01 16:04:35 -04003676 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003677 if (source == nullptr)
3678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003679 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003680 return false;
3681 }
3682
3683 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003686 return false;
3687 }
3688
3689 GLenum sourceTarget = source->getTarget();
3690 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003691
3692 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003695 return false;
3696 }
3697
3698 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3699 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003701 context->handleError(InvalidValue()
3702 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003703 return false;
3704 }
3705
3706 if (x < 0 || y < 0)
3707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003709 return false;
3710 }
3711
3712 if (width < 0 || height < 0)
3713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003714 context->handleError(InvalidValue() << "width and height cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003715 return false;
3716 }
3717
Geoff Lang4f0e0032017-05-01 16:04:35 -04003718 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3719 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003721 context->handleError(InvalidValue() << "Source texture not large enough to copy from.");
Geoff Lang97073d12016-04-20 10:42:34 -07003722 return false;
3723 }
3724
Geoff Lang4f0e0032017-05-01 16:04:35 -04003725 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3726 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003729 return false;
3730 }
3731
Geoff Lang4f0e0032017-05-01 16:04:35 -04003732 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003733 if (dest == nullptr)
3734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidValue()
3736 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003737 return false;
3738 }
3739
Geoff Lang4f0e0032017-05-01 16:04:35 -04003740 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003743 return false;
3744 }
3745
Geoff Lang4f0e0032017-05-01 16:04:35 -04003746 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003749 return false;
3750 }
3751
Geoff Lang4f0e0032017-05-01 16:04:35 -04003752 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3753 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04003754 context
3755 ->handleError(InvalidOperation()
3756 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003757 return false;
3758 }
3759
3760 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3761 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003763 context->handleError(InvalidOperation()
3764 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003765 return false;
3766 }
3767
3768 if (xoffset < 0 || yoffset < 0)
3769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003770 context->handleError(InvalidValue() << "xoffset and yoffset cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003771 return false;
3772 }
3773
Geoff Lang4f0e0032017-05-01 16:04:35 -04003774 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3775 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003777 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003778 return false;
3779 }
3780
3781 return true;
3782}
3783
Geoff Lang47110bf2016-04-20 11:13:22 -07003784bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3785{
3786 if (!context->getExtensions().copyCompressedTexture)
3787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003788 context->handleError(InvalidOperation()
3789 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003790 return false;
3791 }
3792
3793 const gl::Texture *source = context->getTexture(sourceId);
3794 if (source == nullptr)
3795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003797 return false;
3798 }
3799
3800 if (source->getTarget() != GL_TEXTURE_2D)
3801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003802 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003803 return false;
3804 }
3805
3806 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003808 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003809 return false;
3810 }
3811
3812 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3813 if (!sourceFormat.info->compressed)
3814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003815 context->handleError(InvalidOperation()
3816 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003817 return false;
3818 }
3819
3820 const gl::Texture *dest = context->getTexture(destId);
3821 if (dest == nullptr)
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidValue()
3824 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003825 return false;
3826 }
3827
3828 if (dest->getTarget() != GL_TEXTURE_2D)
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidValue()
3831 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003832 return false;
3833 }
3834
3835 if (dest->getImmutableFormat())
3836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003837 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003838 return false;
3839 }
3840
3841 return true;
3842}
3843
Martin Radev4c4c8e72016-08-04 12:25:34 +03003844bool ValidateCreateShader(Context *context, GLenum type)
3845{
3846 switch (type)
3847 {
3848 case GL_VERTEX_SHADER:
3849 case GL_FRAGMENT_SHADER:
3850 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003851
Martin Radev4c4c8e72016-08-04 12:25:34 +03003852 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003853 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003856 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003857 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003858 break;
3859
Martin Radev4c4c8e72016-08-04 12:25:34 +03003860 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidEnum() << "Unknown shader type.");
Martin Radev4c4c8e72016-08-04 12:25:34 +03003862 return false;
3863 }
Jamie Madill29639852016-09-02 15:00:09 -04003864
3865 return true;
3866}
3867
3868bool ValidateBufferData(ValidationContext *context,
3869 GLenum target,
3870 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003871 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003872 GLenum usage)
3873{
3874 if (size < 0)
3875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003876 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003877 return false;
3878 }
3879
3880 switch (usage)
3881 {
3882 case GL_STREAM_DRAW:
3883 case GL_STATIC_DRAW:
3884 case GL_DYNAMIC_DRAW:
3885 break;
3886
3887 case GL_STREAM_READ:
3888 case GL_STREAM_COPY:
3889 case GL_STATIC_READ:
3890 case GL_STATIC_COPY:
3891 case GL_DYNAMIC_READ:
3892 case GL_DYNAMIC_COPY:
3893 if (context->getClientMajorVersion() < 3)
3894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003896 return false;
3897 }
3898 break;
3899
3900 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003901 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003902 return false;
3903 }
3904
3905 if (!ValidBufferTarget(context, target))
3906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003907 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003908 return false;
3909 }
3910
3911 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3912
3913 if (!buffer)
3914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003915 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003916 return false;
3917 }
3918
3919 return true;
3920}
3921
3922bool ValidateBufferSubData(ValidationContext *context,
3923 GLenum target,
3924 GLintptr offset,
3925 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003926 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003927{
3928 if (size < 0 || offset < 0)
3929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003931 return false;
3932 }
3933
3934 if (!ValidBufferTarget(context, target))
3935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003936 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003937 return false;
3938 }
3939
3940 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3941
3942 if (!buffer)
3943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003944 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003945 return false;
3946 }
3947
3948 if (buffer->isMapped())
3949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003950 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003951 return false;
3952 }
3953
3954 // Check for possible overflow of size + offset
3955 angle::CheckedNumeric<size_t> checkedSize(size);
3956 checkedSize += offset;
3957 if (!checkedSize.IsValid())
3958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003959 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04003960 return false;
3961 }
3962
3963 if (size + offset > buffer->getSize())
3964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003965 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003966 return false;
3967 }
3968
Martin Radev4c4c8e72016-08-04 12:25:34 +03003969 return true;
3970}
3971
Geoff Langc339c4e2016-11-29 10:37:36 -05003972bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003973{
Geoff Langc339c4e2016-11-29 10:37:36 -05003974 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003976 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04003977 return false;
3978 }
3979
3980 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3981 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003982 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003984 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04003985 return false;
3986 }
3987
3988 return true;
3989}
3990
Jamie Madillef300b12016-10-07 15:12:09 -04003991bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3992{
3993 if (texture < GL_TEXTURE0 ||
3994 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003996 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04003997 return false;
3998 }
3999
4000 return true;
4001}
4002
4003bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4004{
4005 Program *programObject = GetValidProgram(context, program);
4006 if (!programObject)
4007 {
4008 return false;
4009 }
4010
4011 Shader *shaderObject = GetValidShader(context, shader);
4012 if (!shaderObject)
4013 {
4014 return false;
4015 }
4016
4017 switch (shaderObject->getType())
4018 {
4019 case GL_VERTEX_SHADER:
4020 {
4021 if (programObject->getAttachedVertexShader())
4022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004023 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004024 return false;
4025 }
4026 break;
4027 }
4028 case GL_FRAGMENT_SHADER:
4029 {
4030 if (programObject->getAttachedFragmentShader())
4031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004032 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004033 return false;
4034 }
4035 break;
4036 }
4037 case GL_COMPUTE_SHADER:
4038 {
4039 if (programObject->getAttachedComputeShader())
4040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004041 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004042 return false;
4043 }
4044 break;
4045 }
4046 default:
4047 UNREACHABLE();
4048 break;
4049 }
4050
4051 return true;
4052}
4053
Jamie Madill01a80ee2016-11-07 12:06:18 -05004054bool ValidateBindAttribLocation(ValidationContext *context,
4055 GLuint program,
4056 GLuint index,
4057 const GLchar *name)
4058{
4059 if (index >= MAX_VERTEX_ATTRIBS)
4060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidValue() << "Index exceeds MAX_VERTEX_ATTRIBS");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004062 return false;
4063 }
4064
4065 if (strncmp(name, "gl_", 3) == 0)
4066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004067 context->handleError(InvalidOperation() << "Cannot Bind built-in attributes");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004068 return false;
4069 }
4070
Geoff Langfc32e8b2017-05-31 14:16:59 -04004071 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4072 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004073 if (context->getExtensions().webglCompatibility &&
4074 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004077 return false;
4078 }
4079
Jamie Madill01a80ee2016-11-07 12:06:18 -05004080 return GetValidProgram(context, program) != nullptr;
4081}
4082
4083bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4084{
4085 if (!ValidBufferTarget(context, target))
4086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004087 context->handleError(InvalidEnum() << "Invalid Buffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004088 return false;
4089 }
4090
4091 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4092 !context->isBufferGenerated(buffer))
4093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004094 context->handleError(InvalidOperation() << "Buffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004095 return false;
4096 }
4097
4098 return true;
4099}
4100
4101bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4102{
4103 if (!ValidFramebufferTarget(target))
4104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004105 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004106 return false;
4107 }
4108
4109 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4110 !context->isFramebufferGenerated(framebuffer))
4111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004112 context->handleError(InvalidOperation() << "Framebuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004113 return false;
4114 }
4115
4116 return true;
4117}
4118
4119bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4120{
4121 if (target != GL_RENDERBUFFER)
4122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004123 context->handleError(InvalidEnum() << "Invalid Renderbuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004124 return false;
4125 }
4126
4127 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4128 !context->isRenderbufferGenerated(renderbuffer))
4129 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004130 context->handleError(InvalidOperation() << "Renderbuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004131 return false;
4132 }
4133
4134 return true;
4135}
4136
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004137static bool ValidBlendEquationMode(GLenum mode)
4138{
4139 switch (mode)
4140 {
4141 case GL_FUNC_ADD:
4142 case GL_FUNC_SUBTRACT:
4143 case GL_FUNC_REVERSE_SUBTRACT:
4144 case GL_MIN:
4145 case GL_MAX:
4146 return true;
4147
4148 default:
4149 return false;
4150 }
4151}
4152
Jamie Madillc1d770e2017-04-13 17:31:24 -04004153bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004154 GLfloat red,
4155 GLfloat green,
4156 GLfloat blue,
4157 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004158{
4159 return true;
4160}
4161
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004162bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4163{
4164 if (!ValidBlendEquationMode(mode))
4165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004166 context->handleError(InvalidEnum() << "Invalid blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004167 return false;
4168 }
4169
4170 return true;
4171}
4172
4173bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4174{
4175 if (!ValidBlendEquationMode(modeRGB))
4176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004177 context->handleError(InvalidEnum() << "Invalid RGB blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004178 return false;
4179 }
4180
4181 if (!ValidBlendEquationMode(modeAlpha))
4182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004183 context->handleError(InvalidEnum() << "Invalid alpha blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004184 return false;
4185 }
4186
4187 return true;
4188}
4189
4190bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4191{
4192 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4193}
4194
4195static bool ValidSrcBlendFunc(GLenum srcBlend)
4196{
4197 switch (srcBlend)
4198 {
4199 case GL_ZERO:
4200 case GL_ONE:
4201 case GL_SRC_COLOR:
4202 case GL_ONE_MINUS_SRC_COLOR:
4203 case GL_DST_COLOR:
4204 case GL_ONE_MINUS_DST_COLOR:
4205 case GL_SRC_ALPHA:
4206 case GL_ONE_MINUS_SRC_ALPHA:
4207 case GL_DST_ALPHA:
4208 case GL_ONE_MINUS_DST_ALPHA:
4209 case GL_CONSTANT_COLOR:
4210 case GL_ONE_MINUS_CONSTANT_COLOR:
4211 case GL_CONSTANT_ALPHA:
4212 case GL_ONE_MINUS_CONSTANT_ALPHA:
4213 case GL_SRC_ALPHA_SATURATE:
4214 return true;
4215
4216 default:
4217 return false;
4218 }
4219}
4220
4221static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4222{
4223 switch (dstBlend)
4224 {
4225 case GL_ZERO:
4226 case GL_ONE:
4227 case GL_SRC_COLOR:
4228 case GL_ONE_MINUS_SRC_COLOR:
4229 case GL_DST_COLOR:
4230 case GL_ONE_MINUS_DST_COLOR:
4231 case GL_SRC_ALPHA:
4232 case GL_ONE_MINUS_SRC_ALPHA:
4233 case GL_DST_ALPHA:
4234 case GL_ONE_MINUS_DST_ALPHA:
4235 case GL_CONSTANT_COLOR:
4236 case GL_ONE_MINUS_CONSTANT_COLOR:
4237 case GL_CONSTANT_ALPHA:
4238 case GL_ONE_MINUS_CONSTANT_ALPHA:
4239 return true;
4240
4241 case GL_SRC_ALPHA_SATURATE:
4242 return (contextMajorVersion >= 3);
4243
4244 default:
4245 return false;
4246 }
4247}
4248
4249bool ValidateBlendFuncSeparate(ValidationContext *context,
4250 GLenum srcRGB,
4251 GLenum dstRGB,
4252 GLenum srcAlpha,
4253 GLenum dstAlpha)
4254{
4255 if (!ValidSrcBlendFunc(srcRGB))
4256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004257 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004258 return false;
4259 }
4260
4261 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004263 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004264 return false;
4265 }
4266
4267 if (!ValidSrcBlendFunc(srcAlpha))
4268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004269 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004270 return false;
4271 }
4272
4273 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004275 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004276 return false;
4277 }
4278
Frank Henigman146e8a12017-03-02 23:22:37 -05004279 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4280 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004281 {
4282 bool constantColorUsed =
4283 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4284 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4285
4286 bool constantAlphaUsed =
4287 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4288 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4289
4290 if (constantColorUsed && constantAlphaUsed)
4291 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004292 const char *msg;
4293 if (context->getExtensions().webglCompatibility)
4294 {
4295 msg =
4296 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4297 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4298 }
4299 else
4300 {
4301 msg =
4302 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4303 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4304 "implementation.";
4305 ERR() << msg;
4306 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004307 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004308 return false;
4309 }
4310 }
4311
4312 return true;
4313}
4314
Geoff Langc339c4e2016-11-29 10:37:36 -05004315bool ValidateGetString(Context *context, GLenum name)
4316{
4317 switch (name)
4318 {
4319 case GL_VENDOR:
4320 case GL_RENDERER:
4321 case GL_VERSION:
4322 case GL_SHADING_LANGUAGE_VERSION:
4323 case GL_EXTENSIONS:
4324 break;
4325
4326 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4327 if (!context->getExtensions().requestExtension)
4328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004329 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004330 return false;
4331 }
4332 break;
4333
4334 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004335 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004336 return false;
4337 }
4338
4339 return true;
4340}
4341
Geoff Lang47c48082016-12-07 15:38:13 -05004342bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4343{
4344 if (width <= 0.0f || isNaN(width))
4345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004346 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004347 return false;
4348 }
4349
4350 return true;
4351}
4352
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004353bool ValidateVertexAttribPointer(ValidationContext *context,
4354 GLuint index,
4355 GLint size,
4356 GLenum type,
4357 GLboolean normalized,
4358 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004359 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004360{
Shao80957d92017-02-20 21:25:59 +08004361 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004362 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004363 return false;
4364 }
4365
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004366 if (stride < 0)
4367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004368 context->handleError(InvalidValue() << "stride cannot be negative.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004369 return false;
4370 }
4371
Shao80957d92017-02-20 21:25:59 +08004372 const Caps &caps = context->getCaps();
4373 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004374 {
Shao80957d92017-02-20 21:25:59 +08004375 if (stride > caps.maxVertexAttribStride)
4376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004377 context->handleError(InvalidValue()
4378 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004379 return false;
4380 }
4381
4382 if (index >= caps.maxVertexAttribBindings)
4383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004384 context->handleError(InvalidValue()
4385 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004386 return false;
4387 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004388 }
4389
4390 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4391 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4392 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4393 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004394 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4395 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004396 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004398 context
4399 ->handleError(InvalidOperation()
4400 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004401 return false;
4402 }
4403
4404 if (context->getExtensions().webglCompatibility)
4405 {
4406 // WebGL 1.0 [Section 6.14] Fixed point support
4407 // The WebGL API does not support the GL_FIXED data type.
4408 if (type == GL_FIXED)
4409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004410 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004411 return false;
4412 }
4413
Geoff Lang2d62ab72017-03-23 16:54:40 -04004414 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004415 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004416 return false;
4417 }
4418 }
4419
4420 return true;
4421}
4422
Jamie Madill876429b2017-04-20 15:46:24 -04004423bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004424{
4425 if (context->getExtensions().webglCompatibility && zNear > zFar)
4426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004427 context->handleError(InvalidOperation() << "Depth near > far.");
Frank Henigman6137ddc2017-02-10 18:55:07 -05004428 return false;
4429 }
4430
4431 return true;
4432}
4433
Jamie Madille8fb6402017-02-14 17:56:40 -05004434bool ValidateRenderbufferStorage(ValidationContext *context,
4435 GLenum target,
4436 GLenum internalformat,
4437 GLsizei width,
4438 GLsizei height)
4439{
4440 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4441 height);
4442}
4443
4444bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4445 GLenum target,
4446 GLsizei samples,
4447 GLenum internalformat,
4448 GLsizei width,
4449 GLsizei height)
4450{
4451 if (!context->getExtensions().framebufferMultisample)
4452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004453 context->handleError(InvalidOperation()
4454 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004455 return false;
4456 }
4457
4458 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4459 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4460 // generated.
4461 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004463 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004464 return false;
4465 }
4466
4467 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4468 // the specified storage. This is different than ES 3.0 in which a sample number higher
4469 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4470 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4471 if (context->getClientMajorVersion() >= 3)
4472 {
4473 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4474 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004476 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004477 return false;
4478 }
4479 }
4480
4481 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4482 width, height);
4483}
4484
Jamie Madillc1d770e2017-04-13 17:31:24 -04004485bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4486{
4487 if (!ValidFramebufferTarget(target))
4488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004489 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004490 return false;
4491 }
4492
4493 return true;
4494}
4495
4496bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004497 GLfloat red,
4498 GLfloat green,
4499 GLfloat blue,
4500 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004501{
4502 return true;
4503}
4504
Jamie Madill876429b2017-04-20 15:46:24 -04004505bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004506{
4507 return true;
4508}
4509
4510bool ValidateClearStencil(ValidationContext *context, GLint s)
4511{
4512 return true;
4513}
4514
4515bool ValidateColorMask(ValidationContext *context,
4516 GLboolean red,
4517 GLboolean green,
4518 GLboolean blue,
4519 GLboolean alpha)
4520{
4521 return true;
4522}
4523
4524bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4525{
4526 return true;
4527}
4528
4529bool ValidateCreateProgram(ValidationContext *context)
4530{
4531 return true;
4532}
4533
4534bool ValidateCullFace(ValidationContext *context, GLenum mode)
4535{
4536 switch (mode)
4537 {
4538 case GL_FRONT:
4539 case GL_BACK:
4540 case GL_FRONT_AND_BACK:
4541 break;
4542
4543 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004544 context->handleError(InvalidEnum() << "Invalid cull face parameter");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004545 return false;
4546 }
4547
4548 return true;
4549}
4550
4551bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4552{
4553 if (program == 0)
4554 {
4555 return false;
4556 }
4557
4558 if (!context->getProgram(program))
4559 {
4560 if (context->getShader(program))
4561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004562 context->handleError(InvalidOperation() << "Shader handle passed to DeleteProgram");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004563 return false;
4564 }
4565 else
4566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004567 context->handleError(InvalidValue() << "Invalid program handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004568 return false;
4569 }
4570 }
4571
4572 return true;
4573}
4574
4575bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4576{
4577 if (shader == 0)
4578 {
4579 return false;
4580 }
4581
4582 if (!context->getShader(shader))
4583 {
4584 if (context->getProgram(shader))
4585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004586 context->handleError(InvalidOperation() << "Program handle passed to DeleteShader");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004587 return false;
4588 }
4589 else
4590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004591 context->handleError(InvalidValue() << "Invalid shader handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004592 return false;
4593 }
4594 }
4595
4596 return true;
4597}
4598
4599bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4600{
4601 switch (func)
4602 {
4603 case GL_NEVER:
4604 case GL_ALWAYS:
4605 case GL_LESS:
4606 case GL_LEQUAL:
4607 case GL_EQUAL:
4608 case GL_GREATER:
4609 case GL_GEQUAL:
4610 case GL_NOTEQUAL:
4611 break;
4612
4613 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004614 context->handleError(InvalidEnum() << "Invalid depth function");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004615 return false;
4616 }
4617
4618 return true;
4619}
4620
4621bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4622{
4623 return true;
4624}
4625
4626bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4627{
4628 Program *programObject = GetValidProgram(context, program);
4629 if (!programObject)
4630 {
4631 return false;
4632 }
4633
4634 Shader *shaderObject = GetValidShader(context, shader);
4635 if (!shaderObject)
4636 {
4637 return false;
4638 }
4639
4640 const Shader *attachedShader = nullptr;
4641
4642 switch (shaderObject->getType())
4643 {
4644 case GL_VERTEX_SHADER:
4645 {
4646 attachedShader = programObject->getAttachedVertexShader();
4647 break;
4648 }
4649 case GL_FRAGMENT_SHADER:
4650 {
4651 attachedShader = programObject->getAttachedFragmentShader();
4652 break;
4653 }
4654 case GL_COMPUTE_SHADER:
4655 {
4656 attachedShader = programObject->getAttachedComputeShader();
4657 break;
4658 }
4659 default:
4660 UNREACHABLE();
4661 return false;
4662 }
4663
4664 if (attachedShader != shaderObject)
4665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004666 context->handleError(InvalidOperation() << "Cannot detach non-attached shader.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004667 return false;
4668 }
4669
4670 return true;
4671}
4672
4673bool ValidateDisableVertexAttribArray(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 ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4685{
4686 if (index >= MAX_VERTEX_ATTRIBS)
4687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004688 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004689 return false;
4690 }
4691
4692 return true;
4693}
4694
4695bool ValidateFinish(ValidationContext *context)
4696{
4697 return true;
4698}
4699
4700bool ValidateFlush(ValidationContext *context)
4701{
4702 return true;
4703}
4704
4705bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4706{
4707 switch (mode)
4708 {
4709 case GL_CW:
4710 case GL_CCW:
4711 break;
4712 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004713 context->handleError(InvalidEnum() << "Invalid mode for FrontFace");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004714 return false;
4715 }
4716
4717 return true;
4718}
4719
4720bool ValidateGetActiveAttrib(ValidationContext *context,
4721 GLuint program,
4722 GLuint index,
4723 GLsizei bufsize,
4724 GLsizei *length,
4725 GLint *size,
4726 GLenum *type,
4727 GLchar *name)
4728{
4729 if (bufsize < 0)
4730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004731 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004732 return false;
4733 }
4734
4735 Program *programObject = GetValidProgram(context, program);
4736
4737 if (!programObject)
4738 {
4739 return false;
4740 }
4741
4742 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004744 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004745 return false;
4746 }
4747
4748 return true;
4749}
4750
4751bool ValidateGetActiveUniform(ValidationContext *context,
4752 GLuint program,
4753 GLuint index,
4754 GLsizei bufsize,
4755 GLsizei *length,
4756 GLint *size,
4757 GLenum *type,
4758 GLchar *name)
4759{
4760 if (bufsize < 0)
4761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004762 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004763 return false;
4764 }
4765
4766 Program *programObject = GetValidProgram(context, program);
4767
4768 if (!programObject)
4769 {
4770 return false;
4771 }
4772
4773 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004775 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004776 return false;
4777 }
4778
4779 return true;
4780}
4781
4782bool ValidateGetAttachedShaders(ValidationContext *context,
4783 GLuint program,
4784 GLsizei maxcount,
4785 GLsizei *count,
4786 GLuint *shaders)
4787{
4788 if (maxcount < 0)
4789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004790 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004791 return false;
4792 }
4793
4794 Program *programObject = GetValidProgram(context, program);
4795
4796 if (!programObject)
4797 {
4798 return false;
4799 }
4800
4801 return true;
4802}
4803
4804bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4805{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004806 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4807 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004808 if (context->getExtensions().webglCompatibility &&
4809 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004811 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004812 return false;
4813 }
4814
Jamie Madillc1d770e2017-04-13 17:31:24 -04004815 Program *programObject = GetValidProgram(context, program);
4816
4817 if (!programObject)
4818 {
4819 return false;
4820 }
4821
4822 if (!programObject->isLinked())
4823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004824 context->handleError(InvalidOperation() << "program not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004825 return false;
4826 }
4827
4828 return true;
4829}
4830
4831bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4832{
4833 GLenum nativeType;
4834 unsigned int numParams = 0;
4835 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4836}
4837
4838bool ValidateGetError(ValidationContext *context)
4839{
4840 return true;
4841}
4842
4843bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4844{
4845 GLenum nativeType;
4846 unsigned int numParams = 0;
4847 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4848}
4849
4850bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4851{
4852 GLenum nativeType;
4853 unsigned int numParams = 0;
4854 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4855}
4856
4857bool ValidateGetProgramInfoLog(ValidationContext *context,
4858 GLuint program,
4859 GLsizei bufsize,
4860 GLsizei *length,
4861 GLchar *infolog)
4862{
4863 if (bufsize < 0)
4864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004865 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004866 return false;
4867 }
4868
4869 Program *programObject = GetValidProgram(context, program);
4870 if (!programObject)
4871 {
4872 return false;
4873 }
4874
4875 return true;
4876}
4877
4878bool ValidateGetShaderInfoLog(ValidationContext *context,
4879 GLuint shader,
4880 GLsizei bufsize,
4881 GLsizei *length,
4882 GLchar *infolog)
4883{
4884 if (bufsize < 0)
4885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004886 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004887 return false;
4888 }
4889
4890 Shader *shaderObject = GetValidShader(context, shader);
4891 if (!shaderObject)
4892 {
4893 return false;
4894 }
4895
4896 return true;
4897}
4898
4899bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4900 GLenum shadertype,
4901 GLenum precisiontype,
4902 GLint *range,
4903 GLint *precision)
4904{
4905 switch (shadertype)
4906 {
4907 case GL_VERTEX_SHADER:
4908 case GL_FRAGMENT_SHADER:
4909 break;
4910 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004911 context->handleError(InvalidOperation()
4912 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004913 return false;
4914 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004915 context->handleError(InvalidEnum() << "invalid shader type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004916 return false;
4917 }
4918
4919 switch (precisiontype)
4920 {
4921 case GL_LOW_FLOAT:
4922 case GL_MEDIUM_FLOAT:
4923 case GL_HIGH_FLOAT:
4924 case GL_LOW_INT:
4925 case GL_MEDIUM_INT:
4926 case GL_HIGH_INT:
4927 break;
4928
4929 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004930 context->handleError(InvalidEnum() << "invalid precision type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004931 return false;
4932 }
4933
4934 return true;
4935}
4936
4937bool ValidateGetShaderSource(ValidationContext *context,
4938 GLuint shader,
4939 GLsizei bufsize,
4940 GLsizei *length,
4941 GLchar *source)
4942{
4943 if (bufsize < 0)
4944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004945 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004946 return false;
4947 }
4948
4949 Shader *shaderObject = GetValidShader(context, shader);
4950 if (!shaderObject)
4951 {
4952 return false;
4953 }
4954
4955 return true;
4956}
4957
4958bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4959{
4960 if (strstr(name, "gl_") == name)
4961 {
4962 return false;
4963 }
4964
Geoff Langfc32e8b2017-05-31 14:16:59 -04004965 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4966 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004967 if (context->getExtensions().webglCompatibility &&
4968 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004970 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004971 return false;
4972 }
4973
Jamie Madillc1d770e2017-04-13 17:31:24 -04004974 Program *programObject = GetValidProgram(context, program);
4975
4976 if (!programObject)
4977 {
4978 return false;
4979 }
4980
4981 if (!programObject->isLinked())
4982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004983 context->handleError(InvalidOperation() << "program is not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004984 return false;
4985 }
4986
4987 return true;
4988}
4989
4990bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4991{
4992 switch (mode)
4993 {
4994 case GL_FASTEST:
4995 case GL_NICEST:
4996 case GL_DONT_CARE:
4997 break;
4998
4999 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005000 context->handleError(InvalidEnum() << "invalid hint mode.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005001 return false;
5002 }
5003
5004 switch (target)
5005 {
5006 case GL_GENERATE_MIPMAP_HINT:
5007 break;
5008
5009 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
5010 if (!context->getExtensions().standardDerivatives)
5011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005012 context->handleError(InvalidOperation()
5013 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005014 return false;
5015 }
5016 break;
5017
5018 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005019 context->handleError(InvalidEnum() << "invalid hint target.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005020 return false;
5021 }
5022
5023 return true;
5024}
5025
5026bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5027{
5028 return true;
5029}
5030
5031bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5032{
5033 return true;
5034}
5035
5036bool ValidateIsProgram(ValidationContext *context, GLuint program)
5037{
5038 return true;
5039}
5040
5041bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5042{
5043 return true;
5044}
5045
5046bool ValidateIsShader(ValidationContext *context, GLuint shader)
5047{
5048 return true;
5049}
5050
5051bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5052{
5053 return true;
5054}
5055
5056bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5057{
5058 if (context->getClientMajorVersion() < 3)
5059 {
5060 switch (pname)
5061 {
5062 case GL_UNPACK_IMAGE_HEIGHT:
5063 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005064 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005065 return false;
5066
5067 case GL_UNPACK_ROW_LENGTH:
5068 case GL_UNPACK_SKIP_ROWS:
5069 case GL_UNPACK_SKIP_PIXELS:
5070 if (!context->getExtensions().unpackSubimage)
5071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005072 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005073 return false;
5074 }
5075 break;
5076
5077 case GL_PACK_ROW_LENGTH:
5078 case GL_PACK_SKIP_ROWS:
5079 case GL_PACK_SKIP_PIXELS:
5080 if (!context->getExtensions().packSubimage)
5081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005082 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005083 return false;
5084 }
5085 break;
5086 }
5087 }
5088
5089 if (param < 0)
5090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005091 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005092 return false;
5093 }
5094
5095 switch (pname)
5096 {
5097 case GL_UNPACK_ALIGNMENT:
5098 if (param != 1 && param != 2 && param != 4 && param != 8)
5099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005100 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005101 return false;
5102 }
5103 break;
5104
5105 case GL_PACK_ALIGNMENT:
5106 if (param != 1 && param != 2 && param != 4 && param != 8)
5107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005108 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005109 return false;
5110 }
5111 break;
5112
5113 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5114 case GL_UNPACK_ROW_LENGTH:
5115 case GL_UNPACK_IMAGE_HEIGHT:
5116 case GL_UNPACK_SKIP_IMAGES:
5117 case GL_UNPACK_SKIP_ROWS:
5118 case GL_UNPACK_SKIP_PIXELS:
5119 case GL_PACK_ROW_LENGTH:
5120 case GL_PACK_SKIP_ROWS:
5121 case GL_PACK_SKIP_PIXELS:
5122 break;
5123
5124 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005125 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005126 return false;
5127 }
5128
5129 return true;
5130}
5131
5132bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5133{
5134 return true;
5135}
5136
5137bool ValidateReleaseShaderCompiler(ValidationContext *context)
5138{
5139 return true;
5140}
5141
Jamie Madill876429b2017-04-20 15:46:24 -04005142bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005143{
5144 return true;
5145}
5146
5147bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5148{
5149 if (width < 0 || height < 0)
5150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005151 context->handleError(InvalidValue() << "Scissor width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005152 return false;
5153 }
5154
5155 return true;
5156}
5157
5158bool ValidateShaderBinary(ValidationContext *context,
5159 GLsizei n,
5160 const GLuint *shaders,
5161 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005162 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005163 GLsizei length)
5164{
5165 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5166 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5167 shaderBinaryFormats.end())
5168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005169 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005170 return false;
5171 }
5172
5173 return true;
5174}
5175
5176bool ValidateShaderSource(ValidationContext *context,
5177 GLuint shader,
5178 GLsizei count,
5179 const GLchar *const *string,
5180 const GLint *length)
5181{
5182 if (count < 0)
5183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005184 context->handleError(InvalidValue() << "Count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005185 return false;
5186 }
5187
Geoff Langfc32e8b2017-05-31 14:16:59 -04005188 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5189 // shader-related entry points
5190 if (context->getExtensions().webglCompatibility)
5191 {
5192 for (GLsizei i = 0; i < count; i++)
5193 {
5194 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005195
5196 // Backslash as line-continuation is allowed in WebGL 2.0.
5197 if (!IsValidESSLString(string[i], len, context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005199 context->handleError(InvalidValue() << "Shader source contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04005200 return false;
5201 }
5202 }
5203 }
5204
Jamie Madillc1d770e2017-04-13 17:31:24 -04005205 Shader *shaderObject = GetValidShader(context, shader);
5206 if (!shaderObject)
5207 {
5208 return false;
5209 }
5210
5211 return true;
5212}
5213
5214bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5215{
5216 if (!IsValidStencilFunc(func))
5217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005218 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005219 return false;
5220 }
5221
5222 return true;
5223}
5224
5225bool ValidateStencilFuncSeparate(ValidationContext *context,
5226 GLenum face,
5227 GLenum func,
5228 GLint ref,
5229 GLuint mask)
5230{
5231 if (!IsValidStencilFace(face))
5232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005233 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005234 return false;
5235 }
5236
5237 if (!IsValidStencilFunc(func))
5238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005239 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005240 return false;
5241 }
5242
5243 return true;
5244}
5245
5246bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5247{
5248 return true;
5249}
5250
5251bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5252{
5253 if (!IsValidStencilFace(face))
5254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005255 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005256 return false;
5257 }
5258
5259 return true;
5260}
5261
5262bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5263{
5264 if (!IsValidStencilOp(fail))
5265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005266 context->handleError(InvalidEnum() << "Invalid stencil fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005267 return false;
5268 }
5269
5270 if (!IsValidStencilOp(zfail))
5271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005272 context->handleError(InvalidEnum() << "Invalid stencil z fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005273 return false;
5274 }
5275
5276 if (!IsValidStencilOp(zpass))
5277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005278 context->handleError(InvalidEnum() << "Invalid stencil z pass op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005279 return false;
5280 }
5281
5282 return true;
5283}
5284
5285bool ValidateStencilOpSeparate(ValidationContext *context,
5286 GLenum face,
5287 GLenum fail,
5288 GLenum zfail,
5289 GLenum zpass)
5290{
5291 if (!IsValidStencilFace(face))
5292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005293 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005294 return false;
5295 }
5296
5297 return ValidateStencilOp(context, fail, zfail, zpass);
5298}
5299
5300bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5301{
5302 return ValidateUniform(context, GL_FLOAT, location, 1);
5303}
5304
5305bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5306{
5307 return ValidateUniform(context, GL_FLOAT, location, count);
5308}
5309
Jamie Madillbe849e42017-05-02 15:49:00 -04005310bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5311{
5312 return ValidateUniform1iv(context, location, 1, &x);
5313}
5314
Jamie Madillc1d770e2017-04-13 17:31:24 -04005315bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5316{
5317 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5318}
5319
5320bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5321{
5322 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5323}
5324
5325bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5326{
5327 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5328}
5329
5330bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5331{
5332 return ValidateUniform(context, GL_INT_VEC2, location, count);
5333}
5334
5335bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5336{
5337 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5338}
5339
5340bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5341{
5342 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5343}
5344
5345bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5346{
5347 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5348}
5349
5350bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5351{
5352 return ValidateUniform(context, GL_INT_VEC3, location, count);
5353}
5354
5355bool ValidateUniform4f(ValidationContext *context,
5356 GLint location,
5357 GLfloat x,
5358 GLfloat y,
5359 GLfloat z,
5360 GLfloat w)
5361{
5362 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5363}
5364
5365bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5366{
5367 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5368}
5369
5370bool ValidateUniform4i(ValidationContext *context,
5371 GLint location,
5372 GLint x,
5373 GLint y,
5374 GLint z,
5375 GLint w)
5376{
5377 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5378}
5379
5380bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5381{
5382 return ValidateUniform(context, GL_INT_VEC4, location, count);
5383}
5384
5385bool ValidateUniformMatrix2fv(ValidationContext *context,
5386 GLint location,
5387 GLsizei count,
5388 GLboolean transpose,
5389 const GLfloat *value)
5390{
5391 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5392}
5393
5394bool ValidateUniformMatrix3fv(ValidationContext *context,
5395 GLint location,
5396 GLsizei count,
5397 GLboolean transpose,
5398 const GLfloat *value)
5399{
5400 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5401}
5402
5403bool ValidateUniformMatrix4fv(ValidationContext *context,
5404 GLint location,
5405 GLsizei count,
5406 GLboolean transpose,
5407 const GLfloat *value)
5408{
5409 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5410}
5411
5412bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5413{
5414 Program *programObject = GetValidProgram(context, program);
5415
5416 if (!programObject)
5417 {
5418 return false;
5419 }
5420
5421 return true;
5422}
5423
5424bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5425{
5426 if (index >= MAX_VERTEX_ATTRIBS)
5427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005428 context->handleError(InvalidValue() << "Vertex attrib index out of range.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005429 return false;
5430 }
5431
5432 return true;
5433}
5434
5435bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5436{
5437 return ValidateVertexAttribIndex(context, index);
5438}
5439
5440bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5441{
5442 return ValidateVertexAttribIndex(context, index);
5443}
5444
5445bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5446{
5447 return ValidateVertexAttribIndex(context, index);
5448}
5449
5450bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5451{
5452 return ValidateVertexAttribIndex(context, index);
5453}
5454
5455bool ValidateVertexAttrib3f(ValidationContext *context,
5456 GLuint index,
5457 GLfloat x,
5458 GLfloat y,
5459 GLfloat z)
5460{
5461 return ValidateVertexAttribIndex(context, index);
5462}
5463
5464bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5465{
5466 return ValidateVertexAttribIndex(context, index);
5467}
5468
5469bool ValidateVertexAttrib4f(ValidationContext *context,
5470 GLuint index,
5471 GLfloat x,
5472 GLfloat y,
5473 GLfloat z,
5474 GLfloat w)
5475{
5476 return ValidateVertexAttribIndex(context, index);
5477}
5478
5479bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5480{
5481 return ValidateVertexAttribIndex(context, index);
5482}
5483
5484bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5485{
5486 if (width < 0 || height < 0)
5487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005488 context->handleError(InvalidValue() << "Viewport width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005489 return false;
5490 }
5491
5492 return true;
5493}
5494
5495bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5496{
5497 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5498}
5499
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005500bool ValidateDrawElements(ValidationContext *context,
5501 GLenum mode,
5502 GLsizei count,
5503 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005504 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005505{
5506 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5507}
5508
Jamie Madillbe849e42017-05-02 15:49:00 -04005509bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5510 GLenum target,
5511 GLenum attachment,
5512 GLenum pname,
5513 GLint *params)
5514{
5515 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5516 nullptr);
5517}
5518
5519bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5520{
5521 return ValidateGetProgramivBase(context, program, pname, nullptr);
5522}
5523
5524bool ValidateCopyTexImage2D(ValidationContext *context,
5525 GLenum target,
5526 GLint level,
5527 GLenum internalformat,
5528 GLint x,
5529 GLint y,
5530 GLsizei width,
5531 GLsizei height,
5532 GLint border)
5533{
5534 if (context->getClientMajorVersion() < 3)
5535 {
5536 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5537 0, x, y, width, height, border);
5538 }
5539
5540 ASSERT(context->getClientMajorVersion() == 3);
5541 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5542 0, x, y, width, height, border);
5543}
5544
5545bool ValidateCopyTexSubImage2D(Context *context,
5546 GLenum target,
5547 GLint level,
5548 GLint xoffset,
5549 GLint yoffset,
5550 GLint x,
5551 GLint y,
5552 GLsizei width,
5553 GLsizei height)
5554{
5555 if (context->getClientMajorVersion() < 3)
5556 {
5557 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5558 yoffset, x, y, width, height, 0);
5559 }
5560
5561 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5562 yoffset, 0, x, y, width, height, 0);
5563}
5564
5565bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5566{
5567 return ValidateGenOrDelete(context, n);
5568}
5569
5570bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5571{
5572 return ValidateGenOrDelete(context, n);
5573}
5574
5575bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5576{
5577 return ValidateGenOrDelete(context, n);
5578}
5579
5580bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5581{
5582 return ValidateGenOrDelete(context, n);
5583}
5584
5585bool ValidateDisable(Context *context, GLenum cap)
5586{
5587 if (!ValidCap(context, cap, false))
5588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005589 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 return false;
5591 }
5592
5593 return true;
5594}
5595
5596bool ValidateEnable(Context *context, GLenum cap)
5597{
5598 if (!ValidCap(context, cap, false))
5599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005600 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603
5604 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5605 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5606 {
5607 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005608 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005609
5610 // We also output an error message to the debugger window if tracing is active, so that
5611 // developers can see the error message.
5612 ERR() << errorMessage;
5613 return false;
5614 }
5615
5616 return true;
5617}
5618
5619bool ValidateFramebufferRenderbuffer(Context *context,
5620 GLenum target,
5621 GLenum attachment,
5622 GLenum renderbuffertarget,
5623 GLuint renderbuffer)
5624{
5625 if (!ValidFramebufferTarget(target) ||
5626 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005628 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005629 return false;
5630 }
5631
5632 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5633 renderbuffertarget, renderbuffer);
5634}
5635
5636bool ValidateFramebufferTexture2D(Context *context,
5637 GLenum target,
5638 GLenum attachment,
5639 GLenum textarget,
5640 GLuint texture,
5641 GLint level)
5642{
5643 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5644 // extension
5645 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5646 level != 0)
5647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005648 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005649 return false;
5650 }
5651
5652 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5653 {
5654 return false;
5655 }
5656
5657 if (texture != 0)
5658 {
5659 gl::Texture *tex = context->getTexture(texture);
5660 ASSERT(tex);
5661
5662 const gl::Caps &caps = context->getCaps();
5663
5664 switch (textarget)
5665 {
5666 case GL_TEXTURE_2D:
5667 {
5668 if (level > gl::log2(caps.max2DTextureSize))
5669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005670 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005671 return false;
5672 }
5673 if (tex->getTarget() != GL_TEXTURE_2D)
5674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005675 context->handleError(InvalidOperation()
5676 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 return false;
5678 }
5679 }
5680 break;
5681
5682 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5684 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5688 {
5689 if (level > gl::log2(caps.maxCubeMapTextureSize))
5690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005691 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005692 return false;
5693 }
5694 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005696 context->handleError(InvalidOperation()
5697 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005698 return false;
5699 }
5700 }
5701 break;
5702
5703 case GL_TEXTURE_2D_MULTISAMPLE:
5704 {
5705 if (context->getClientVersion() < ES_3_1)
5706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005707 context->handleError(InvalidOperation()
5708 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005709 return false;
5710 }
5711
5712 if (level != 0)
5713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005714 context->handleError(InvalidValue()
5715 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005716 return false;
5717 }
5718 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005720 context->handleError(InvalidOperation()
5721 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005722 return false;
5723 }
5724 }
5725 break;
5726
5727 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005728 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005729 return false;
5730 }
5731
5732 const Format &format = tex->getFormat(textarget, level);
5733 if (format.info->compressed)
5734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005735 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005736 return false;
5737 }
5738 }
5739
5740 return true;
5741}
5742
5743bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5744{
5745 return ValidateGenOrDelete(context, n);
5746}
5747
5748bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5749{
5750 return ValidateGenOrDelete(context, n);
5751}
5752
5753bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5754{
5755 return ValidateGenOrDelete(context, n);
5756}
5757
5758bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5759{
5760 return ValidateGenOrDelete(context, n);
5761}
5762
5763bool ValidateGenerateMipmap(Context *context, GLenum target)
5764{
5765 if (!ValidTextureTarget(context, target))
5766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005767 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005768 return false;
5769 }
5770
5771 Texture *texture = context->getTargetTexture(target);
5772
5773 if (texture == nullptr)
5774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005775 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005776 return false;
5777 }
5778
5779 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5780
5781 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5782 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5783 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005785 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 return false;
5787 }
5788
5789 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5790 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5791 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5792
5793 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5794 // unsized formats or that are color renderable and filterable. Since we do not track if
5795 // the texture was created with sized or unsized format (only sized formats are stored),
5796 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5797 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5798 // textures since they're the only texture format that can be created with unsized formats
5799 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5800 // was the last version to use add them.
5801 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5802 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005804 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 return false;
5806 }
5807
Geoff Lang65ac5b92017-05-01 13:16:30 -04005808 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5809 bool supportsSRGBMipmapGeneration =
5810 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5811 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005813 context->handleError(InvalidOperation()
5814 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817
5818 // Non-power of 2 ES2 check
5819 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5820 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5821 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5822 {
5823 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005824 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005825 return false;
5826 }
5827
5828 // Cube completeness check
5829 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005831 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005832 return false;
5833 }
5834
5835 return true;
5836}
5837
5838bool ValidateGetBufferParameteriv(ValidationContext *context,
5839 GLenum target,
5840 GLenum pname,
5841 GLint *params)
5842{
5843 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5844}
5845
5846bool ValidateGetRenderbufferParameteriv(Context *context,
5847 GLenum target,
5848 GLenum pname,
5849 GLint *params)
5850{
5851 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5852}
5853
5854bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5855{
5856 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5857}
5858
5859bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5860{
5861 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5862}
5863
5864bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5865{
5866 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5867}
5868
5869bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5870{
5871 return ValidateGetUniformBase(context, program, location);
5872}
5873
5874bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5875{
5876 return ValidateGetUniformBase(context, program, location);
5877}
5878
5879bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5880{
5881 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5882}
5883
5884bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5885{
5886 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5887}
5888
5889bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5890{
5891 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5892}
5893
5894bool ValidateIsEnabled(Context *context, GLenum cap)
5895{
5896 if (!ValidCap(context, cap, true))
5897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005898 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005899 return false;
5900 }
5901
5902 return true;
5903}
5904
5905bool ValidateLinkProgram(Context *context, GLuint program)
5906{
5907 if (context->hasActiveTransformFeedback(program))
5908 {
5909 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005910 context->handleError(InvalidOperation() << "Cannot link program while program is "
5911 "associated with an active transform "
5912 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005913 return false;
5914 }
5915
5916 Program *programObject = GetValidProgram(context, program);
5917 if (!programObject)
5918 {
5919 return false;
5920 }
5921
5922 return true;
5923}
5924
Jamie Madill4928b7c2017-06-20 12:57:39 -04005925bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005926 GLint x,
5927 GLint y,
5928 GLsizei width,
5929 GLsizei height,
5930 GLenum format,
5931 GLenum type,
5932 void *pixels)
5933{
5934 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5935 nullptr, pixels);
5936}
5937
5938bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5939{
5940 return ValidateTexParameterBase(context, target, pname, -1, &param);
5941}
5942
5943bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5944{
5945 return ValidateTexParameterBase(context, target, pname, -1, params);
5946}
5947
5948bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5949{
5950 return ValidateTexParameterBase(context, target, pname, -1, &param);
5951}
5952
5953bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5954{
5955 return ValidateTexParameterBase(context, target, pname, -1, params);
5956}
5957
5958bool ValidateUseProgram(Context *context, GLuint program)
5959{
5960 if (program != 0)
5961 {
5962 Program *programObject = context->getProgram(program);
5963 if (!programObject)
5964 {
5965 // ES 3.1.0 section 7.3 page 72
5966 if (context->getShader(program))
5967 {
5968 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005969 InvalidOperation()
5970 << "Attempted to use a single shader instead of a shader program.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005971 return false;
5972 }
5973 else
5974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005975 context->handleError(InvalidValue() << "Program invalid.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005976 return false;
5977 }
5978 }
5979 if (!programObject->isLinked())
5980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005981 context->handleError(InvalidOperation() << "Program not linked.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005982 return false;
5983 }
5984 }
5985 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5986 {
5987 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005988 context
5989 ->handleError(InvalidOperation()
5990 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 return false;
5992 }
5993
5994 return true;
5995}
5996
Jamie Madillc29968b2016-01-20 11:17:23 -05005997} // namespace gl