blob: 80aa0fb2d100546e628ff5a343b139136d3656ed [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
364 if (level > 0 && context->getClientVersion() < ES_3_0)
365 {
366 return false;
367 }
368
369 const Caps &caps = context->getCaps();
370 if (target == GL_TEXTURE_2D)
371 {
372 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
373 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
374 {
375 return false;
376 }
377 }
378 else if (IsCubeMapTextureTarget(target))
379 {
380 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
381 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
382 {
383 return false;
384 }
385 }
386
387 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700388}
389
Jamie Madillc1d770e2017-04-13 17:31:24 -0400390bool IsValidStencilFunc(GLenum func)
391{
392 switch (func)
393 {
394 case GL_NEVER:
395 case GL_ALWAYS:
396 case GL_LESS:
397 case GL_LEQUAL:
398 case GL_EQUAL:
399 case GL_GEQUAL:
400 case GL_GREATER:
401 case GL_NOTEQUAL:
402 return true;
403
404 default:
405 return false;
406 }
407}
408
409bool IsValidStencilFace(GLenum face)
410{
411 switch (face)
412 {
413 case GL_FRONT:
414 case GL_BACK:
415 case GL_FRONT_AND_BACK:
416 return true;
417
418 default:
419 return false;
420 }
421}
422
423bool IsValidStencilOp(GLenum op)
424{
425 switch (op)
426 {
427 case GL_ZERO:
428 case GL_KEEP:
429 case GL_REPLACE:
430 case GL_INCR:
431 case GL_DECR:
432 case GL_INVERT:
433 case GL_INCR_WRAP:
434 case GL_DECR_WRAP:
435 return true;
436
437 default:
438 return false;
439 }
440}
441
Jamie Madillbe849e42017-05-02 15:49:00 -0400442bool ValidateES2CopyTexImageParameters(ValidationContext *context,
443 GLenum target,
444 GLint level,
445 GLenum internalformat,
446 bool isSubImage,
447 GLint xoffset,
448 GLint yoffset,
449 GLint x,
450 GLint y,
451 GLsizei width,
452 GLsizei height,
453 GLint border)
454{
455 if (!ValidTexture2DDestinationTarget(context, target))
456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500457 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -0400458 return false;
459 }
460
461 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500463 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400464 return false;
465 }
466
467 Format textureFormat = Format::Invalid();
468 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
469 xoffset, yoffset, 0, x, y, width, height, border,
470 &textureFormat))
471 {
472 return false;
473 }
474
475 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
476 GLenum colorbufferFormat =
477 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
478 const auto &formatInfo = *textureFormat.info;
479
480 // [OpenGL ES 2.0.24] table 3.9
481 if (isSubImage)
482 {
483 switch (formatInfo.format)
484 {
485 case GL_ALPHA:
486 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400487 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
488 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500490 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400491 return false;
492 }
493 break;
494 case GL_LUMINANCE:
495 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
496 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
497 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400498 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
499 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500501 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400502 return false;
503 }
504 break;
505 case GL_RED_EXT:
506 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
507 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
508 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
509 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
510 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400511 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
512 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500514 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400515 return false;
516 }
517 break;
518 case GL_RG_EXT:
519 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
520 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
521 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
522 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400523 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
524 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500526 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400527 return false;
528 }
529 break;
530 case GL_RGB:
531 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
532 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
533 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400534 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
535 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500537 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400538 return false;
539 }
540 break;
541 case GL_LUMINANCE_ALPHA:
542 case GL_RGBA:
543 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400544 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
545 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500547 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400548 return false;
549 }
550 break;
551 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
552 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
553 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
554 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
555 case GL_ETC1_RGB8_OES:
556 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
557 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
558 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
559 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
560 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500561 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 return false;
563 case GL_DEPTH_COMPONENT:
564 case GL_DEPTH_STENCIL_OES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500565 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400566 return false;
567 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500568 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400569 return false;
570 }
571
572 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500574 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400575 return false;
576 }
577 }
578 else
579 {
580 switch (internalformat)
581 {
582 case GL_ALPHA:
583 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
584 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
585 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500587 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400588 return false;
589 }
590 break;
591 case GL_LUMINANCE:
592 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
593 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
594 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
595 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
596 colorbufferFormat != GL_BGR5_A1_ANGLEX)
597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500598 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400599 return false;
600 }
601 break;
602 case GL_RED_EXT:
603 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
604 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
605 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
606 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
607 colorbufferFormat != GL_BGR5_A1_ANGLEX)
608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500609 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400610 return false;
611 }
612 break;
613 case GL_RG_EXT:
614 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
615 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
616 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
617 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500619 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400620 return false;
621 }
622 break;
623 case GL_RGB:
624 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
625 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
626 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
627 colorbufferFormat != GL_BGR5_A1_ANGLEX)
628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500629 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400630 return false;
631 }
632 break;
633 case GL_LUMINANCE_ALPHA:
634 case GL_RGBA:
635 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
636 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
637 colorbufferFormat != GL_BGR5_A1_ANGLEX)
638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500639 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400640 return false;
641 }
642 break;
643 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
644 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
645 if (context->getExtensions().textureCompressionDXT1)
646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500647 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400648 return false;
649 }
650 else
651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500652 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400653 return false;
654 }
655 break;
656 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
657 if (context->getExtensions().textureCompressionDXT3)
658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500659 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400660 return false;
661 }
662 else
663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500664 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666 }
667 break;
668 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
669 if (context->getExtensions().textureCompressionDXT5)
670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500671 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400672 return false;
673 }
674 else
675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500676 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400677 return false;
678 }
679 break;
680 case GL_ETC1_RGB8_OES:
681 if (context->getExtensions().compressedETC1RGB8Texture)
682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500683 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400684 return false;
685 }
686 else
687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500688 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 return false;
690 }
691 break;
692 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
693 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
694 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
695 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
696 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
697 if (context->getExtensions().lossyETCDecode)
698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 context->handleError(InvalidOperation()
700 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400701 return false;
702 }
703 else
704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500705 context->handleError(InvalidEnum()
706 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400707 return false;
708 }
709 break;
710 case GL_DEPTH_COMPONENT:
711 case GL_DEPTH_COMPONENT16:
712 case GL_DEPTH_COMPONENT32_OES:
713 case GL_DEPTH_STENCIL_OES:
714 case GL_DEPTH24_STENCIL8_OES:
715 if (context->getExtensions().depthTextures)
716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500717 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400718 return false;
719 }
720 else
721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500722 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400727 return false;
728 }
729 }
730
731 // If width or height is zero, it is a no-op. Return false without setting an error.
732 return (width > 0 && height > 0);
733}
734
735bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
736{
737 switch (cap)
738 {
739 // EXT_multisample_compatibility
740 case GL_MULTISAMPLE_EXT:
741 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
742 return context->getExtensions().multisampleCompatibility;
743
744 case GL_CULL_FACE:
745 case GL_POLYGON_OFFSET_FILL:
746 case GL_SAMPLE_ALPHA_TO_COVERAGE:
747 case GL_SAMPLE_COVERAGE:
748 case GL_SCISSOR_TEST:
749 case GL_STENCIL_TEST:
750 case GL_DEPTH_TEST:
751 case GL_BLEND:
752 case GL_DITHER:
753 return true;
754
755 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
756 case GL_RASTERIZER_DISCARD:
757 return (context->getClientMajorVersion() >= 3);
758
759 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
760 case GL_DEBUG_OUTPUT:
761 return context->getExtensions().debug;
762
763 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
764 return queryOnly && context->getExtensions().bindGeneratesResource;
765
766 case GL_CLIENT_ARRAYS_ANGLE:
767 return queryOnly && context->getExtensions().clientArrays;
768
769 case GL_FRAMEBUFFER_SRGB_EXT:
770 return context->getExtensions().sRGBWriteControl;
771
772 case GL_SAMPLE_MASK:
773 return context->getClientVersion() >= Version(3, 1);
774
775 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
776 return queryOnly && context->getExtensions().robustResourceInitialization;
777
778 default:
779 return false;
780 }
781}
782
Geoff Langfc32e8b2017-05-31 14:16:59 -0400783// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
784// 3.1.
785bool IsValidESSLCharacter(unsigned char c)
786{
787 // Printing characters are valid except " $ ` @ \ ' DEL.
788 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
789 c != '\'')
790 {
791 return true;
792 }
793
794 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
795 if (c >= 9 && c <= 13)
796 {
797 return true;
798 }
799
800 return false;
801}
802
803bool IsValidESSLString(const char *str, size_t len)
804{
805 return len == 0 || std::find_if_not(str, str + len, IsValidESSLCharacter) == str + len;
806}
807
Jamie Madillc29968b2016-01-20 11:17:23 -0500808} // anonymous namespace
809
Geoff Langff5b2d52016-09-07 11:32:23 -0400810bool ValidateES2TexImageParameters(Context *context,
811 GLenum target,
812 GLint level,
813 GLenum internalformat,
814 bool isCompressed,
815 bool isSubImage,
816 GLint xoffset,
817 GLint yoffset,
818 GLsizei width,
819 GLsizei height,
820 GLint border,
821 GLenum format,
822 GLenum type,
823 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400824 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825{
Jamie Madill6f38f822014-06-06 17:12:20 -0400826 if (!ValidTexture2DDestinationTarget(context, target))
827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500828 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400830 }
831
Austin Kinross08528e12015-10-07 16:24:40 -0700832 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500834 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 }
837
He Yunchaoced53ae2016-11-29 15:00:51 +0800838 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 std::numeric_limits<GLsizei>::max() - yoffset < height)
840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500841 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 }
844
Geoff Lang6e898aa2017-06-02 11:17:26 -0400845 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
846 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
847 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
848 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
849 // case.
850 bool nonEqualFormatsAllowed =
851 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
852 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
853
854 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500856 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400857 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 }
859
Geoff Langaae65a42014-05-26 12:43:44 -0400860 const gl::Caps &caps = context->getCaps();
861
Geoff Langa9be0dc2014-12-17 12:34:40 -0500862 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500864 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
865 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500867 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500868 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500870 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500871 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500872 {
873 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500875 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500876 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878
Geoff Langa9be0dc2014-12-17 12:34:40 -0500879 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
880 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500882 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500883 return false;
884 }
885 }
886 else
887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500888 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400889 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400890 }
891
He Yunchaoced53ae2016-11-29 15:00:51 +0800892 gl::Texture *texture =
893 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894 if (!texture)
895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500896 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400897 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400898 }
899
Geoff Langa9be0dc2014-12-17 12:34:40 -0500900 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901 {
Geoff Langca271392017-04-05 12:30:00 -0400902 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
903 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500905 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500906 return false;
907 }
908
Geoff Langa9be0dc2014-12-17 12:34:40 -0500909 if (format != GL_NONE)
910 {
Geoff Langca271392017-04-05 12:30:00 -0400911 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
912 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500914 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500915 return false;
916 }
917 }
918
919 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
920 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500922 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500923 return false;
924 }
925 }
926 else
927 {
Geoff Lang69cce582015-09-17 13:20:36 -0400928 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500930 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500931 return false;
932 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400933 }
934
935 // Verify zero border
936 if (border != 0)
937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500938 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400939 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 }
941
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 if (isCompressed)
943 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400944 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400945 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
946 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 switch (actualInternalFormat)
948 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800949 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
950 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
951 if (!context->getExtensions().textureCompressionDXT1)
952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500953 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800954 return false;
955 }
956 break;
957 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
958 if (!context->getExtensions().textureCompressionDXT1)
959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500960 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800961 return false;
962 }
963 break;
964 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
965 if (!context->getExtensions().textureCompressionDXT5)
966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500967 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800968 return false;
969 }
970 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800971 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
972 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
973 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
974 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
975 if (!context->getExtensions().textureCompressionS3TCsRGB)
976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500977 context->handleError(InvalidEnum());
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800978 return false;
979 }
980 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 case GL_ETC1_RGB8_OES:
982 if (!context->getExtensions().compressedETC1RGB8Texture)
983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500984 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 return false;
986 }
987 break;
988 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800989 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
990 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
991 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
992 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800993 if (!context->getExtensions().lossyETCDecode)
994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500995 context->handleError(InvalidEnum()
996 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 return false;
998 }
999 break;
1000 default:
1001 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001002 InvalidEnum()
1003 << "internalformat is not a supported compressed internal format");
Geoff Langb1196682014-07-23 13:47:29 -04001004 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001005 }
Geoff Lang966c9402017-04-18 12:38:27 -04001006
1007 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001008 {
Geoff Lang966c9402017-04-18 12:38:27 -04001009 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1010 height, texture->getWidth(target, level),
1011 texture->getHeight(target, level)))
1012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001014 return false;
1015 }
1016
1017 if (format != actualInternalFormat)
1018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidOperation()
1020 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -04001021 return false;
1022 }
1023 }
1024 else
1025 {
1026 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001028 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001029 return false;
1030 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 }
1032 }
1033 else
1034 {
1035 // validate <type> by itself (used as secondary key below)
1036 switch (type)
1037 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001038 case GL_UNSIGNED_BYTE:
1039 case GL_UNSIGNED_SHORT_5_6_5:
1040 case GL_UNSIGNED_SHORT_4_4_4_4:
1041 case GL_UNSIGNED_SHORT_5_5_5_1:
1042 case GL_UNSIGNED_SHORT:
1043 case GL_UNSIGNED_INT:
1044 case GL_UNSIGNED_INT_24_8_OES:
1045 case GL_HALF_FLOAT_OES:
1046 case GL_FLOAT:
1047 break;
1048 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001049 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052
1053 // validate <format> + <type> combinations
1054 // - invalid <format> -> sets INVALID_ENUM
1055 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1056 switch (format)
1057 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 case GL_ALPHA:
1059 case GL_LUMINANCE:
1060 case GL_LUMINANCE_ALPHA:
1061 switch (type)
1062 {
1063 case GL_UNSIGNED_BYTE:
1064 case GL_FLOAT:
1065 case GL_HALF_FLOAT_OES:
1066 break;
1067 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001068 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001069 return false;
1070 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_RED:
1073 case GL_RG:
1074 if (!context->getExtensions().textureRG)
1075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001076 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 return false;
1078 }
1079 switch (type)
1080 {
1081 case GL_UNSIGNED_BYTE:
1082 case GL_FLOAT:
1083 case GL_HALF_FLOAT_OES:
1084 break;
1085 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001086 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001087 return false;
1088 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001090 case GL_RGB:
1091 switch (type)
1092 {
1093 case GL_UNSIGNED_BYTE:
1094 case GL_UNSIGNED_SHORT_5_6_5:
1095 case GL_FLOAT:
1096 case GL_HALF_FLOAT_OES:
1097 break;
1098 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001099 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001100 return false;
1101 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001102 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 case GL_RGBA:
1104 switch (type)
1105 {
1106 case GL_UNSIGNED_BYTE:
1107 case GL_UNSIGNED_SHORT_4_4_4_4:
1108 case GL_UNSIGNED_SHORT_5_5_5_1:
1109 case GL_FLOAT:
1110 case GL_HALF_FLOAT_OES:
1111 break;
1112 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001113 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 return false;
1115 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 case GL_BGRA_EXT:
1118 switch (type)
1119 {
1120 case GL_UNSIGNED_BYTE:
1121 break;
1122 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001123 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 return false;
1125 }
1126 break;
1127 case GL_SRGB_EXT:
1128 case GL_SRGB_ALPHA_EXT:
1129 if (!context->getExtensions().sRGB)
1130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001131 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001132 return false;
1133 }
1134 switch (type)
1135 {
1136 case GL_UNSIGNED_BYTE:
1137 break;
1138 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001139 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 return false;
1141 }
1142 break;
1143 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1144 // handled below
1145 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1146 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1147 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1148 break;
1149 case GL_DEPTH_COMPONENT:
1150 switch (type)
1151 {
1152 case GL_UNSIGNED_SHORT:
1153 case GL_UNSIGNED_INT:
1154 break;
1155 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001157 return false;
1158 }
1159 break;
1160 case GL_DEPTH_STENCIL_OES:
1161 switch (type)
1162 {
1163 case GL_UNSIGNED_INT_24_8_OES:
1164 break;
1165 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001166 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001167 return false;
1168 }
1169 break;
1170 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
1175 switch (format)
1176 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1178 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1179 if (context->getExtensions().textureCompressionDXT1)
1180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001181 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001182 return false;
1183 }
1184 else
1185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001186 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001187 return false;
1188 }
1189 break;
1190 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1191 if (context->getExtensions().textureCompressionDXT3)
1192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 return false;
1195 }
1196 else
1197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001198 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001199 return false;
1200 }
1201 break;
1202 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1203 if (context->getExtensions().textureCompressionDXT5)
1204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001205 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return false;
1207 }
1208 else
1209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001210 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001211 return false;
1212 }
1213 break;
1214 case GL_ETC1_RGB8_OES:
1215 if (context->getExtensions().compressedETC1RGB8Texture)
1216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001217 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 return false;
1219 }
1220 else
1221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001222 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001223 return false;
1224 }
1225 break;
1226 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001227 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1228 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1229 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1230 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001231 if (context->getExtensions().lossyETCDecode)
1232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidOperation()
1234 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001235 return false;
1236 }
1237 else
1238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001239 context->handleError(InvalidEnum()
1240 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001241 return false;
1242 }
1243 break;
1244 case GL_DEPTH_COMPONENT:
1245 case GL_DEPTH_STENCIL_OES:
1246 if (!context->getExtensions().depthTextures)
1247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001249 return false;
1250 }
1251 if (target != GL_TEXTURE_2D)
1252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001253 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001254 return false;
1255 }
1256 // OES_depth_texture supports loading depth data and multiple levels,
1257 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001258 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001261 return false;
1262 }
1263 break;
1264 default:
1265 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001266 }
1267
Geoff Lang6e898aa2017-06-02 11:17:26 -04001268 if (!isSubImage)
1269 {
1270 switch (internalformat)
1271 {
1272 case GL_RGBA32F:
1273 if (!context->getExtensions().colorBufferFloatRGBA)
1274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001275 context->handleError(InvalidValue()
1276 << "Sized GL_RGBA32F internal format requires "
1277 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001278 return false;
1279 }
1280 if (type != GL_FLOAT)
1281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001282 context->handleError(InvalidOperation()
1283 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001284 return false;
1285 }
1286 if (format != GL_RGBA)
1287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001288 context->handleError(InvalidOperation()
1289 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001290 return false;
1291 }
1292 break;
1293
1294 case GL_RGB32F:
1295 if (!context->getExtensions().colorBufferFloatRGB)
1296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001297 context->handleError(InvalidValue()
1298 << "Sized GL_RGB32F internal format requires "
1299 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001300 return false;
1301 }
1302 if (type != GL_FLOAT)
1303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001304 context->handleError(InvalidOperation()
1305 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001306 return false;
1307 }
1308 if (format != GL_RGB)
1309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001310 context->handleError(InvalidOperation()
1311 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001312 return false;
1313 }
1314 break;
1315
1316 default:
1317 break;
1318 }
1319 }
1320
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 if (type == GL_FLOAT)
1322 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001323 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 }
1328 }
1329 else if (type == GL_HALF_FLOAT_OES)
1330 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001331 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001333 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 }
1336 }
1337 }
1338
Geoff Langdbcced82017-06-06 15:55:54 -04001339 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1340 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001341 imageSize))
1342 {
1343 return false;
1344 }
1345
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001346 return true;
1347}
1348
He Yunchaoced53ae2016-11-29 15:00:51 +08001349bool ValidateES2TexStorageParameters(Context *context,
1350 GLenum target,
1351 GLsizei levels,
1352 GLenum internalformat,
1353 GLsizei width,
1354 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355{
1356 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001358 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 }
1361
1362 if (width < 1 || height < 1 || levels < 1)
1363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
1367
1368 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001371 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 }
1373
1374 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001377 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 }
1379
Geoff Langca271392017-04-05 12:30:00 -04001380 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001381 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 }
1386
Geoff Langaae65a42014-05-26 12:43:44 -04001387 const gl::Caps &caps = context->getCaps();
1388
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 switch (target)
1390 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001391 case GL_TEXTURE_2D:
1392 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1393 static_cast<GLuint>(height) > caps.max2DTextureSize)
1394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001396 return false;
1397 }
1398 break;
1399 case GL_TEXTURE_CUBE_MAP:
1400 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1401 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001404 return false;
1405 }
1406 break;
1407 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001408 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001409 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 }
1411
Geoff Langc0b9ef42014-07-02 10:02:37 -04001412 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 {
1414 if (!gl::isPow2(width) || !gl::isPow2(height))
1415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001417 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 }
1419 }
1420
1421 switch (internalformat)
1422 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001423 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1424 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1425 if (!context->getExtensions().textureCompressionDXT1)
1426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001428 return false;
1429 }
1430 break;
1431 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1432 if (!context->getExtensions().textureCompressionDXT3)
1433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001435 return false;
1436 }
1437 break;
1438 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1439 if (!context->getExtensions().textureCompressionDXT5)
1440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001441 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001442 return false;
1443 }
1444 break;
1445 case GL_ETC1_RGB8_OES:
1446 if (!context->getExtensions().compressedETC1RGB8Texture)
1447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001449 return false;
1450 }
1451 break;
1452 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001453 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1454 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1455 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1456 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001457 if (!context->getExtensions().lossyETCDecode)
1458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001459 context->handleError(InvalidEnum()
1460 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 return false;
1462 }
1463 break;
1464 case GL_RGBA32F_EXT:
1465 case GL_RGB32F_EXT:
1466 case GL_ALPHA32F_EXT:
1467 case GL_LUMINANCE32F_EXT:
1468 case GL_LUMINANCE_ALPHA32F_EXT:
1469 if (!context->getExtensions().textureFloat)
1470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001471 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
1473 }
1474 break;
1475 case GL_RGBA16F_EXT:
1476 case GL_RGB16F_EXT:
1477 case GL_ALPHA16F_EXT:
1478 case GL_LUMINANCE16F_EXT:
1479 case GL_LUMINANCE_ALPHA16F_EXT:
1480 if (!context->getExtensions().textureHalfFloat)
1481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001482 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001483 return false;
1484 }
1485 break;
1486 case GL_R8_EXT:
1487 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001488 if (!context->getExtensions().textureRG)
1489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001490 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001491 return false;
1492 }
1493 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_R16F_EXT:
1495 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001496 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001498 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001499 return false;
1500 }
1501 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001502 case GL_R32F_EXT:
1503 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001504 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001507 return false;
1508 }
1509 break;
1510 case GL_DEPTH_COMPONENT16:
1511 case GL_DEPTH_COMPONENT32_OES:
1512 case GL_DEPTH24_STENCIL8_OES:
1513 if (!context->getExtensions().depthTextures)
1514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001515 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001516 return false;
1517 }
1518 if (target != GL_TEXTURE_2D)
1519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001520 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001521 return false;
1522 }
1523 // ANGLE_depth_texture only supports 1-level textures
1524 if (levels != 1)
1525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001526 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001527 return false;
1528 }
1529 break;
1530 default:
1531 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001532 }
1533
Geoff Lang691e58c2014-12-19 17:03:25 -05001534 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 if (!texture || texture->id() == 0)
1536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001537 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001538 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 }
1540
Geoff Lang69cce582015-09-17 13:20:36 -04001541 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001543 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001544 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001545 }
1546
1547 return true;
1548}
1549
He Yunchaoced53ae2016-11-29 15:00:51 +08001550bool ValidateDiscardFramebufferEXT(Context *context,
1551 GLenum target,
1552 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001553 const GLenum *attachments)
1554{
Jamie Madillc29968b2016-01-20 11:17:23 -05001555 if (!context->getExtensions().discardFramebuffer)
1556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001557 context->handleError(InvalidOperation() << "Extension not enabled");
Jamie Madillc29968b2016-01-20 11:17:23 -05001558 return false;
1559 }
1560
Austin Kinross08332632015-05-05 13:35:47 -07001561 bool defaultFramebuffer = false;
1562
1563 switch (target)
1564 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001565 case GL_FRAMEBUFFER:
1566 defaultFramebuffer =
1567 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1568 break;
1569 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001570 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001571 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001572 }
1573
He Yunchaoced53ae2016-11-29 15:00:51 +08001574 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1575 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001576}
1577
Austin Kinrossbc781f32015-10-26 09:27:38 -07001578bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1579{
1580 if (!context->getExtensions().vertexArrayObject)
1581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001582 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001583 return false;
1584 }
1585
1586 return ValidateBindVertexArrayBase(context, array);
1587}
1588
1589bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1590{
1591 if (!context->getExtensions().vertexArrayObject)
1592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001593 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001594 return false;
1595 }
1596
Olli Etuaho41997e72016-03-10 13:38:39 +02001597 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001598}
1599
1600bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1601{
1602 if (!context->getExtensions().vertexArrayObject)
1603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001605 return false;
1606 }
1607
Olli Etuaho41997e72016-03-10 13:38:39 +02001608 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001609}
1610
1611bool ValidateIsVertexArrayOES(Context *context)
1612{
1613 if (!context->getExtensions().vertexArrayObject)
1614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001615 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001616 return false;
1617 }
1618
1619 return true;
1620}
Geoff Langc5629752015-12-07 16:29:04 -05001621
1622bool ValidateProgramBinaryOES(Context *context,
1623 GLuint program,
1624 GLenum binaryFormat,
1625 const void *binary,
1626 GLint length)
1627{
1628 if (!context->getExtensions().getProgramBinary)
1629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001630 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001631 return false;
1632 }
1633
1634 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1635}
1636
1637bool ValidateGetProgramBinaryOES(Context *context,
1638 GLuint program,
1639 GLsizei bufSize,
1640 GLsizei *length,
1641 GLenum *binaryFormat,
1642 void *binary)
1643{
1644 if (!context->getExtensions().getProgramBinary)
1645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001647 return false;
1648 }
1649
1650 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1651}
Geoff Lange102fee2015-12-10 11:23:30 -05001652
Geoff Lang70d0f492015-12-10 17:45:46 -05001653static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1654{
1655 switch (source)
1656 {
1657 case GL_DEBUG_SOURCE_API:
1658 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1659 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1660 case GL_DEBUG_SOURCE_OTHER:
1661 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1662 return !mustBeThirdPartyOrApplication;
1663
1664 case GL_DEBUG_SOURCE_THIRD_PARTY:
1665 case GL_DEBUG_SOURCE_APPLICATION:
1666 return true;
1667
1668 default:
1669 return false;
1670 }
1671}
1672
1673static bool ValidDebugType(GLenum type)
1674{
1675 switch (type)
1676 {
1677 case GL_DEBUG_TYPE_ERROR:
1678 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1679 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1680 case GL_DEBUG_TYPE_PERFORMANCE:
1681 case GL_DEBUG_TYPE_PORTABILITY:
1682 case GL_DEBUG_TYPE_OTHER:
1683 case GL_DEBUG_TYPE_MARKER:
1684 case GL_DEBUG_TYPE_PUSH_GROUP:
1685 case GL_DEBUG_TYPE_POP_GROUP:
1686 return true;
1687
1688 default:
1689 return false;
1690 }
1691}
1692
1693static bool ValidDebugSeverity(GLenum severity)
1694{
1695 switch (severity)
1696 {
1697 case GL_DEBUG_SEVERITY_HIGH:
1698 case GL_DEBUG_SEVERITY_MEDIUM:
1699 case GL_DEBUG_SEVERITY_LOW:
1700 case GL_DEBUG_SEVERITY_NOTIFICATION:
1701 return true;
1702
1703 default:
1704 return false;
1705 }
1706}
1707
Geoff Lange102fee2015-12-10 11:23:30 -05001708bool ValidateDebugMessageControlKHR(Context *context,
1709 GLenum source,
1710 GLenum type,
1711 GLenum severity,
1712 GLsizei count,
1713 const GLuint *ids,
1714 GLboolean enabled)
1715{
1716 if (!context->getExtensions().debug)
1717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001718 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001719 return false;
1720 }
1721
Geoff Lang70d0f492015-12-10 17:45:46 -05001722 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001725 return false;
1726 }
1727
1728 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001730 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001731 return false;
1732 }
1733
1734 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001737 return false;
1738 }
1739
1740 if (count > 0)
1741 {
1742 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 context->handleError(
1745 InvalidOperation()
1746 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001747 return false;
1748 }
1749
1750 if (severity != GL_DONT_CARE)
1751 {
Jamie Madill437fa652016-05-03 15:13:24 -04001752 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001753 InvalidOperation()
1754 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001755 return false;
1756 }
1757 }
1758
Geoff Lange102fee2015-12-10 11:23:30 -05001759 return true;
1760}
1761
1762bool ValidateDebugMessageInsertKHR(Context *context,
1763 GLenum source,
1764 GLenum type,
1765 GLuint id,
1766 GLenum severity,
1767 GLsizei length,
1768 const GLchar *buf)
1769{
1770 if (!context->getExtensions().debug)
1771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001772 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001773 return false;
1774 }
1775
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001776 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001777 {
1778 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1779 // not generate an error.
1780 return false;
1781 }
1782
1783 if (!ValidDebugSeverity(severity))
1784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001785 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001786 return false;
1787 }
1788
1789 if (!ValidDebugType(type))
1790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001791 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001792 return false;
1793 }
1794
1795 if (!ValidDebugSource(source, true))
1796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001797 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001798 return false;
1799 }
1800
1801 size_t messageLength = (length < 0) ? strlen(buf) : length;
1802 if (messageLength > context->getExtensions().maxDebugMessageLength)
1803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001804 context->handleError(InvalidValue()
1805 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001806 return false;
1807 }
1808
Geoff Lange102fee2015-12-10 11:23:30 -05001809 return true;
1810}
1811
1812bool ValidateDebugMessageCallbackKHR(Context *context,
1813 GLDEBUGPROCKHR callback,
1814 const void *userParam)
1815{
1816 if (!context->getExtensions().debug)
1817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001818 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001819 return false;
1820 }
1821
Geoff Lange102fee2015-12-10 11:23:30 -05001822 return true;
1823}
1824
1825bool ValidateGetDebugMessageLogKHR(Context *context,
1826 GLuint count,
1827 GLsizei bufSize,
1828 GLenum *sources,
1829 GLenum *types,
1830 GLuint *ids,
1831 GLenum *severities,
1832 GLsizei *lengths,
1833 GLchar *messageLog)
1834{
1835 if (!context->getExtensions().debug)
1836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001837 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001838 return false;
1839 }
1840
Geoff Lang70d0f492015-12-10 17:45:46 -05001841 if (bufSize < 0 && messageLog != nullptr)
1842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001843 context->handleError(InvalidValue()
1844 << "bufSize must be positive if messageLog is not null.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001845 return false;
1846 }
1847
Geoff Lange102fee2015-12-10 11:23:30 -05001848 return true;
1849}
1850
1851bool ValidatePushDebugGroupKHR(Context *context,
1852 GLenum source,
1853 GLuint id,
1854 GLsizei length,
1855 const GLchar *message)
1856{
1857 if (!context->getExtensions().debug)
1858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001859 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001860 return false;
1861 }
1862
Geoff Lang70d0f492015-12-10 17:45:46 -05001863 if (!ValidDebugSource(source, true))
1864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001865 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001866 return false;
1867 }
1868
1869 size_t messageLength = (length < 0) ? strlen(message) : length;
1870 if (messageLength > context->getExtensions().maxDebugMessageLength)
1871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001872 context->handleError(InvalidValue()
1873 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001874 return false;
1875 }
1876
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001877 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001878 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1879 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001880 context
1881 ->handleError(StackOverflow()
1882 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001883 return false;
1884 }
1885
Geoff Lange102fee2015-12-10 11:23:30 -05001886 return true;
1887}
1888
1889bool ValidatePopDebugGroupKHR(Context *context)
1890{
1891 if (!context->getExtensions().debug)
1892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001893 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001894 return false;
1895 }
1896
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001897 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001898 if (currentStackSize <= 1)
1899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001900 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001901 return false;
1902 }
1903
1904 return true;
1905}
1906
1907static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1908{
1909 switch (identifier)
1910 {
1911 case GL_BUFFER:
1912 if (context->getBuffer(name) == nullptr)
1913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001914 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001915 return false;
1916 }
1917 return true;
1918
1919 case GL_SHADER:
1920 if (context->getShader(name) == nullptr)
1921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001922 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001923 return false;
1924 }
1925 return true;
1926
1927 case GL_PROGRAM:
1928 if (context->getProgram(name) == nullptr)
1929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001930 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001931 return false;
1932 }
1933 return true;
1934
1935 case GL_VERTEX_ARRAY:
1936 if (context->getVertexArray(name) == nullptr)
1937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001938 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001939 return false;
1940 }
1941 return true;
1942
1943 case GL_QUERY:
1944 if (context->getQuery(name) == nullptr)
1945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001946 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001947 return false;
1948 }
1949 return true;
1950
1951 case GL_TRANSFORM_FEEDBACK:
1952 if (context->getTransformFeedback(name) == nullptr)
1953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001954 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001955 return false;
1956 }
1957 return true;
1958
1959 case GL_SAMPLER:
1960 if (context->getSampler(name) == nullptr)
1961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001962 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001963 return false;
1964 }
1965 return true;
1966
1967 case GL_TEXTURE:
1968 if (context->getTexture(name) == nullptr)
1969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001970 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001971 return false;
1972 }
1973 return true;
1974
1975 case GL_RENDERBUFFER:
1976 if (context->getRenderbuffer(name) == nullptr)
1977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001978 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001979 return false;
1980 }
1981 return true;
1982
1983 case GL_FRAMEBUFFER:
1984 if (context->getFramebuffer(name) == nullptr)
1985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001986 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001987 return false;
1988 }
1989 return true;
1990
1991 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001992 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001993 return false;
1994 }
Geoff Lange102fee2015-12-10 11:23:30 -05001995}
1996
Martin Radev9d901792016-07-15 15:58:58 +03001997static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1998{
1999 size_t labelLength = 0;
2000
2001 if (length < 0)
2002 {
2003 if (label != nullptr)
2004 {
2005 labelLength = strlen(label);
2006 }
2007 }
2008 else
2009 {
2010 labelLength = static_cast<size_t>(length);
2011 }
2012
2013 if (labelLength > context->getExtensions().maxLabelLength)
2014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002015 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002016 return false;
2017 }
2018
2019 return true;
2020}
2021
Geoff Lange102fee2015-12-10 11:23:30 -05002022bool ValidateObjectLabelKHR(Context *context,
2023 GLenum identifier,
2024 GLuint name,
2025 GLsizei length,
2026 const GLchar *label)
2027{
2028 if (!context->getExtensions().debug)
2029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002030 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002031 return false;
2032 }
2033
Geoff Lang70d0f492015-12-10 17:45:46 -05002034 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2035 {
2036 return false;
2037 }
2038
Martin Radev9d901792016-07-15 15:58:58 +03002039 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002040 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002041 return false;
2042 }
2043
Geoff Lange102fee2015-12-10 11:23:30 -05002044 return true;
2045}
2046
2047bool ValidateGetObjectLabelKHR(Context *context,
2048 GLenum identifier,
2049 GLuint name,
2050 GLsizei bufSize,
2051 GLsizei *length,
2052 GLchar *label)
2053{
2054 if (!context->getExtensions().debug)
2055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002056 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002057 return false;
2058 }
2059
Geoff Lang70d0f492015-12-10 17:45:46 -05002060 if (bufSize < 0)
2061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002062 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002063 return false;
2064 }
2065
2066 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2067 {
2068 return false;
2069 }
2070
Martin Radev9d901792016-07-15 15:58:58 +03002071 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002072}
2073
2074static bool ValidateObjectPtrName(Context *context, const void *ptr)
2075{
2076 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002078 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002079 return false;
2080 }
2081
Geoff Lange102fee2015-12-10 11:23:30 -05002082 return true;
2083}
2084
2085bool ValidateObjectPtrLabelKHR(Context *context,
2086 const void *ptr,
2087 GLsizei length,
2088 const GLchar *label)
2089{
2090 if (!context->getExtensions().debug)
2091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002092 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002093 return false;
2094 }
2095
Geoff Lang70d0f492015-12-10 17:45:46 -05002096 if (!ValidateObjectPtrName(context, ptr))
2097 {
2098 return false;
2099 }
2100
Martin Radev9d901792016-07-15 15:58:58 +03002101 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002102 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002103 return false;
2104 }
2105
Geoff Lange102fee2015-12-10 11:23:30 -05002106 return true;
2107}
2108
2109bool ValidateGetObjectPtrLabelKHR(Context *context,
2110 const void *ptr,
2111 GLsizei bufSize,
2112 GLsizei *length,
2113 GLchar *label)
2114{
2115 if (!context->getExtensions().debug)
2116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002117 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002118 return false;
2119 }
2120
Geoff Lang70d0f492015-12-10 17:45:46 -05002121 if (bufSize < 0)
2122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002123 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002124 return false;
2125 }
2126
2127 if (!ValidateObjectPtrName(context, ptr))
2128 {
2129 return false;
2130 }
2131
Martin Radev9d901792016-07-15 15:58:58 +03002132 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002133}
2134
2135bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2136{
2137 if (!context->getExtensions().debug)
2138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002139 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002140 return false;
2141 }
2142
Geoff Lang70d0f492015-12-10 17:45:46 -05002143 // TODO: represent this in Context::getQueryParameterInfo.
2144 switch (pname)
2145 {
2146 case GL_DEBUG_CALLBACK_FUNCTION:
2147 case GL_DEBUG_CALLBACK_USER_PARAM:
2148 break;
2149
2150 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002151 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002152 return false;
2153 }
2154
Geoff Lange102fee2015-12-10 11:23:30 -05002155 return true;
2156}
Jamie Madillc29968b2016-01-20 11:17:23 -05002157
2158bool ValidateBlitFramebufferANGLE(Context *context,
2159 GLint srcX0,
2160 GLint srcY0,
2161 GLint srcX1,
2162 GLint srcY1,
2163 GLint dstX0,
2164 GLint dstY0,
2165 GLint dstX1,
2166 GLint dstY1,
2167 GLbitfield mask,
2168 GLenum filter)
2169{
2170 if (!context->getExtensions().framebufferBlit)
2171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002172 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002173 return false;
2174 }
2175
2176 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2177 {
2178 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidOperation() << "Scaling and flipping in "
2180 "BlitFramebufferANGLE not supported by this "
2181 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002182 return false;
2183 }
2184
2185 if (filter == GL_LINEAR)
2186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002187 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002188 return false;
2189 }
2190
Jamie Madill51f40ec2016-06-15 14:06:00 -04002191 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2192 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002193
2194 if (mask & GL_COLOR_BUFFER_BIT)
2195 {
2196 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2197 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2198
2199 if (readColorAttachment && drawColorAttachment)
2200 {
2201 if (!(readColorAttachment->type() == GL_TEXTURE &&
2202 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2203 readColorAttachment->type() != GL_RENDERBUFFER &&
2204 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002206 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002207 return false;
2208 }
2209
Geoff Langa15472a2015-08-11 11:48:03 -04002210 for (size_t drawbufferIdx = 0;
2211 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002212 {
Geoff Langa15472a2015-08-11 11:48:03 -04002213 const FramebufferAttachment *attachment =
2214 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2215 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002216 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002217 if (!(attachment->type() == GL_TEXTURE &&
2218 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2219 attachment->type() != GL_RENDERBUFFER &&
2220 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002223 return false;
2224 }
2225
2226 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002227 if (!Format::SameSized(attachment->getFormat(),
2228 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002230 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002231 return false;
2232 }
2233 }
2234 }
2235
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002236 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002237 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2238 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002240 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002241 return false;
2242 }
2243 }
2244 }
2245
2246 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2247 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2248 for (size_t i = 0; i < 2; i++)
2249 {
2250 if (mask & masks[i])
2251 {
2252 const FramebufferAttachment *readBuffer =
2253 readFramebuffer->getAttachment(attachments[i]);
2254 const FramebufferAttachment *drawBuffer =
2255 drawFramebuffer->getAttachment(attachments[i]);
2256
2257 if (readBuffer && drawBuffer)
2258 {
2259 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2260 dstX0, dstY0, dstX1, dstY1))
2261 {
2262 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002263 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2264 "stencil blits are supported by "
2265 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002266 return false;
2267 }
2268
2269 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002272 return false;
2273 }
2274 }
2275 }
2276 }
2277
2278 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2279 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002280}
Jamie Madillc29968b2016-01-20 11:17:23 -05002281
2282bool ValidateClear(ValidationContext *context, GLbitfield mask)
2283{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002284 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002285 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002287 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002288 return false;
2289 }
2290
2291 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002293 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05002294 return false;
2295 }
2296
Geoff Lang76e65652017-03-27 14:58:02 -04002297 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2298 {
2299 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2300 GL_SIGNED_NORMALIZED};
2301
2302 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2303 drawBufferIdx++)
2304 {
2305 if (!ValidateWebGLFramebufferAttachmentClearType(
2306 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2307 {
2308 return false;
2309 }
2310 }
2311 }
2312
Jamie Madillc29968b2016-01-20 11:17:23 -05002313 return true;
2314}
2315
2316bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2317{
2318 if (!context->getExtensions().drawBuffers)
2319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002320 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002321 return false;
2322 }
2323
2324 return ValidateDrawBuffersBase(context, n, bufs);
2325}
2326
Jamie Madill73a84962016-02-12 09:27:23 -05002327bool ValidateTexImage2D(Context *context,
2328 GLenum target,
2329 GLint level,
2330 GLint internalformat,
2331 GLsizei width,
2332 GLsizei height,
2333 GLint border,
2334 GLenum format,
2335 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002336 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002337{
Martin Radev1be913c2016-07-11 17:59:16 +03002338 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002339 {
2340 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002341 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002342 }
2343
Martin Radev1be913c2016-07-11 17:59:16 +03002344 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002345 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002346 0, 0, width, height, 1, border, format, type, -1,
2347 pixels);
2348}
2349
2350bool ValidateTexImage2DRobust(Context *context,
2351 GLenum target,
2352 GLint level,
2353 GLint internalformat,
2354 GLsizei width,
2355 GLsizei height,
2356 GLint border,
2357 GLenum format,
2358 GLenum type,
2359 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002360 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002361{
2362 if (!ValidateRobustEntryPoint(context, bufSize))
2363 {
2364 return false;
2365 }
2366
2367 if (context->getClientMajorVersion() < 3)
2368 {
2369 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2370 0, 0, width, height, border, format, type, bufSize,
2371 pixels);
2372 }
2373
2374 ASSERT(context->getClientMajorVersion() >= 3);
2375 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2376 0, 0, width, height, 1, border, format, type, bufSize,
2377 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002378}
2379
2380bool ValidateTexSubImage2D(Context *context,
2381 GLenum target,
2382 GLint level,
2383 GLint xoffset,
2384 GLint yoffset,
2385 GLsizei width,
2386 GLsizei height,
2387 GLenum format,
2388 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002389 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002390{
2391
Martin Radev1be913c2016-07-11 17:59:16 +03002392 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002393 {
2394 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002395 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002396 }
2397
Martin Radev1be913c2016-07-11 17:59:16 +03002398 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002399 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002400 yoffset, 0, width, height, 1, 0, format, type, -1,
2401 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002402}
2403
Geoff Langc52f6f12016-10-14 10:18:00 -04002404bool ValidateTexSubImage2DRobustANGLE(Context *context,
2405 GLenum target,
2406 GLint level,
2407 GLint xoffset,
2408 GLint yoffset,
2409 GLsizei width,
2410 GLsizei height,
2411 GLenum format,
2412 GLenum type,
2413 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002414 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002415{
2416 if (!ValidateRobustEntryPoint(context, bufSize))
2417 {
2418 return false;
2419 }
2420
2421 if (context->getClientMajorVersion() < 3)
2422 {
2423 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2424 yoffset, width, height, 0, format, type, bufSize,
2425 pixels);
2426 }
2427
2428 ASSERT(context->getClientMajorVersion() >= 3);
2429 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2430 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2431 pixels);
2432}
2433
Jamie Madill73a84962016-02-12 09:27:23 -05002434bool ValidateCompressedTexImage2D(Context *context,
2435 GLenum target,
2436 GLint level,
2437 GLenum internalformat,
2438 GLsizei width,
2439 GLsizei height,
2440 GLint border,
2441 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002442 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002443{
Martin Radev1be913c2016-07-11 17:59:16 +03002444 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002445 {
2446 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002447 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002448 {
2449 return false;
2450 }
2451 }
2452 else
2453 {
Martin Radev1be913c2016-07-11 17:59:16 +03002454 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002455 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002456 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002457 data))
2458 {
2459 return false;
2460 }
2461 }
2462
Geoff Langca271392017-04-05 12:30:00 -04002463 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002464 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002465 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002466 if (blockSizeOrErr.isError())
2467 {
2468 context->handleError(blockSizeOrErr.getError());
2469 return false;
2470 }
2471
2472 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002474 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002475 return false;
2476 }
2477
2478 return true;
2479}
2480
Corentin Wallezb2931602017-04-11 15:58:57 -04002481bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2482 GLenum target,
2483 GLint level,
2484 GLenum internalformat,
2485 GLsizei width,
2486 GLsizei height,
2487 GLint border,
2488 GLsizei imageSize,
2489 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002490 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002491{
2492 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2493 {
2494 return false;
2495 }
2496
2497 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2498 border, imageSize, data);
2499}
2500bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2501 GLenum target,
2502 GLint level,
2503 GLint xoffset,
2504 GLint yoffset,
2505 GLsizei width,
2506 GLsizei height,
2507 GLenum format,
2508 GLsizei imageSize,
2509 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002510 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002511{
2512 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2513 {
2514 return false;
2515 }
2516
2517 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2518 format, imageSize, data);
2519}
2520
Jamie Madill73a84962016-02-12 09:27:23 -05002521bool ValidateCompressedTexSubImage2D(Context *context,
2522 GLenum target,
2523 GLint level,
2524 GLint xoffset,
2525 GLint yoffset,
2526 GLsizei width,
2527 GLsizei height,
2528 GLenum format,
2529 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002530 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002531{
Martin Radev1be913c2016-07-11 17:59:16 +03002532 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002533 {
2534 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002535 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002536 {
2537 return false;
2538 }
2539 }
2540 else
2541 {
Martin Radev1be913c2016-07-11 17:59:16 +03002542 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002543 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002544 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002545 data))
2546 {
2547 return false;
2548 }
2549 }
2550
Geoff Langca271392017-04-05 12:30:00 -04002551 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002552 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002553 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002554 if (blockSizeOrErr.isError())
2555 {
2556 context->handleError(blockSizeOrErr.getError());
2557 return false;
2558 }
2559
2560 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002562 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002563 return false;
2564 }
2565
2566 return true;
2567}
2568
Olli Etuaho4f667482016-03-30 15:56:35 +03002569bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2570{
Geoff Lang496c02d2016-10-20 11:38:11 -07002571 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002572}
2573
2574bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2575{
2576 if (!context->getExtensions().mapBuffer)
2577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002578 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002579 return false;
2580 }
2581
2582 if (!ValidBufferTarget(context, target))
2583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002584 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002585 return false;
2586 }
2587
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002588 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002589
2590 if (buffer == nullptr)
2591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002592 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002593 return false;
2594 }
2595
2596 if (access != GL_WRITE_ONLY_OES)
2597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002599 return false;
2600 }
2601
2602 if (buffer->isMapped())
2603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002604 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002605 return false;
2606 }
2607
2608 return true;
2609}
2610
2611bool ValidateUnmapBufferOES(Context *context, GLenum target)
2612{
2613 if (!context->getExtensions().mapBuffer)
2614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002615 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002616 return false;
2617 }
2618
2619 return ValidateUnmapBufferBase(context, target);
2620}
2621
2622bool ValidateMapBufferRangeEXT(Context *context,
2623 GLenum target,
2624 GLintptr offset,
2625 GLsizeiptr length,
2626 GLbitfield access)
2627{
2628 if (!context->getExtensions().mapBufferRange)
2629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002630 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002631 return false;
2632 }
2633
2634 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2635}
2636
2637bool ValidateFlushMappedBufferRangeEXT(Context *context,
2638 GLenum target,
2639 GLintptr offset,
2640 GLsizeiptr length)
2641{
2642 if (!context->getExtensions().mapBufferRange)
2643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002644 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002645 return false;
2646 }
2647
2648 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2649}
2650
Ian Ewell54f87462016-03-10 13:47:21 -05002651bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2652{
2653 Texture *textureObject = context->getTexture(texture);
2654 if (textureObject && textureObject->getTarget() != target && texture != 0)
2655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002656 context->handleError(InvalidOperation() << "Invalid texture");
Ian Ewell54f87462016-03-10 13:47:21 -05002657 return false;
2658 }
2659
Geoff Langf41a7152016-09-19 15:11:17 -04002660 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2661 !context->isTextureGenerated(texture))
2662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002663 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002664 return false;
2665 }
2666
Ian Ewell54f87462016-03-10 13:47:21 -05002667 switch (target)
2668 {
2669 case GL_TEXTURE_2D:
2670 case GL_TEXTURE_CUBE_MAP:
2671 break;
2672
2673 case GL_TEXTURE_3D:
2674 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002675 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002677 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002678 return false;
2679 }
2680 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002681
2682 case GL_TEXTURE_2D_MULTISAMPLE:
2683 if (context->getClientVersion() < Version(3, 1))
2684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002685 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002686 return false;
2687 }
Geoff Lang3b573612016-10-31 14:08:10 -04002688 break;
2689
Ian Ewell54f87462016-03-10 13:47:21 -05002690 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002691 if (!context->getExtensions().eglImageExternal &&
2692 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002694 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002695 return false;
2696 }
2697 break;
2698 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002699 context->handleError(InvalidEnum() << "Invalid target");
Ian Ewell54f87462016-03-10 13:47:21 -05002700 return false;
2701 }
2702
2703 return true;
2704}
2705
Geoff Langd8605522016-04-13 10:19:12 -04002706bool ValidateBindUniformLocationCHROMIUM(Context *context,
2707 GLuint program,
2708 GLint location,
2709 const GLchar *name)
2710{
2711 if (!context->getExtensions().bindUniformLocation)
2712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002713 context->handleError(InvalidOperation()
2714 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002715 return false;
2716 }
2717
2718 Program *programObject = GetValidProgram(context, program);
2719 if (!programObject)
2720 {
2721 return false;
2722 }
2723
2724 if (location < 0)
2725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002726 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002727 return false;
2728 }
2729
2730 const Caps &caps = context->getCaps();
2731 if (static_cast<size_t>(location) >=
2732 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002734 context->handleError(InvalidValue() << "Location must be less than "
2735 "(MAX_VERTEX_UNIFORM_VECTORS + "
2736 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002737 return false;
2738 }
2739
Geoff Langfc32e8b2017-05-31 14:16:59 -04002740 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2741 // shader-related entry points
2742 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
2743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002744 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04002745 return false;
2746 }
2747
Geoff Langd8605522016-04-13 10:19:12 -04002748 if (strncmp(name, "gl_", 3) == 0)
2749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002750 context->handleError(InvalidOperation()
2751 << "Name cannot start with the reserved \"gl_\" prefix.");
Geoff Langd8605522016-04-13 10:19:12 -04002752 return false;
2753 }
2754
2755 return true;
2756}
2757
Jamie Madille2e406c2016-06-02 13:04:10 -04002758bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002759{
2760 if (!context->getExtensions().framebufferMixedSamples)
2761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002762 context->handleError(InvalidOperation()
2763 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002764 return false;
2765 }
2766 switch (components)
2767 {
2768 case GL_RGB:
2769 case GL_RGBA:
2770 case GL_ALPHA:
2771 case GL_NONE:
2772 break;
2773 default:
2774 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002775 InvalidEnum()
2776 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002777 return false;
2778 }
2779
2780 return true;
2781}
2782
Sami Väisänene45e53b2016-05-25 10:36:04 +03002783// CHROMIUM_path_rendering
2784
2785bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2786{
2787 if (!context->getExtensions().pathRendering)
2788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002789 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002790 return false;
2791 }
2792 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002794 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002795 return false;
2796 }
2797 if (matrix == nullptr)
2798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002799 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002800 return false;
2801 }
2802 return true;
2803}
2804
2805bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2806{
2807 if (!context->getExtensions().pathRendering)
2808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002809 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002810 return false;
2811 }
2812 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002814 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002815 return false;
2816 }
2817 return true;
2818}
2819
2820bool ValidateGenPaths(Context *context, GLsizei range)
2821{
2822 if (!context->getExtensions().pathRendering)
2823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002824 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002825 return false;
2826 }
2827
2828 // range = 0 is undefined in NV_path_rendering.
2829 // we add stricter semantic check here and require a non zero positive range.
2830 if (range <= 0)
2831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002832 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002833 return false;
2834 }
2835
2836 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002838 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002839 return false;
2840 }
2841
2842 return true;
2843}
2844
2845bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2846{
2847 if (!context->getExtensions().pathRendering)
2848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002849 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002850 return false;
2851 }
2852
2853 // range = 0 is undefined in NV_path_rendering.
2854 // we add stricter semantic check here and require a non zero positive range.
2855 if (range <= 0)
2856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002857 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002858 return false;
2859 }
2860
2861 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2862 checkedRange += range;
2863
2864 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002866 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002867 return false;
2868 }
2869 return true;
2870}
2871
2872bool ValidatePathCommands(Context *context,
2873 GLuint path,
2874 GLsizei numCommands,
2875 const GLubyte *commands,
2876 GLsizei numCoords,
2877 GLenum coordType,
2878 const void *coords)
2879{
2880 if (!context->getExtensions().pathRendering)
2881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002882 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002883 return false;
2884 }
2885 if (!context->hasPath(path))
2886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002887 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002888 return false;
2889 }
2890
2891 if (numCommands < 0)
2892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002893 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002894 return false;
2895 }
2896 else if (numCommands > 0)
2897 {
2898 if (!commands)
2899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002900 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002901 return false;
2902 }
2903 }
2904
2905 if (numCoords < 0)
2906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002907 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002908 return false;
2909 }
2910 else if (numCoords > 0)
2911 {
2912 if (!coords)
2913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002914 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002915 return false;
2916 }
2917 }
2918
2919 std::uint32_t coordTypeSize = 0;
2920 switch (coordType)
2921 {
2922 case GL_BYTE:
2923 coordTypeSize = sizeof(GLbyte);
2924 break;
2925
2926 case GL_UNSIGNED_BYTE:
2927 coordTypeSize = sizeof(GLubyte);
2928 break;
2929
2930 case GL_SHORT:
2931 coordTypeSize = sizeof(GLshort);
2932 break;
2933
2934 case GL_UNSIGNED_SHORT:
2935 coordTypeSize = sizeof(GLushort);
2936 break;
2937
2938 case GL_FLOAT:
2939 coordTypeSize = sizeof(GLfloat);
2940 break;
2941
2942 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002943 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002944 return false;
2945 }
2946
2947 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2948 checkedSize += (coordTypeSize * numCoords);
2949 if (!checkedSize.IsValid())
2950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002951 context->handleError(InvalidOperation() << "Coord size overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002952 return false;
2953 }
2954
2955 // early return skips command data validation when it doesn't exist.
2956 if (!commands)
2957 return true;
2958
2959 GLsizei expectedNumCoords = 0;
2960 for (GLsizei i = 0; i < numCommands; ++i)
2961 {
2962 switch (commands[i])
2963 {
2964 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2965 break;
2966 case GL_MOVE_TO_CHROMIUM:
2967 case GL_LINE_TO_CHROMIUM:
2968 expectedNumCoords += 2;
2969 break;
2970 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2971 expectedNumCoords += 4;
2972 break;
2973 case GL_CUBIC_CURVE_TO_CHROMIUM:
2974 expectedNumCoords += 6;
2975 break;
2976 case GL_CONIC_CURVE_TO_CHROMIUM:
2977 expectedNumCoords += 5;
2978 break;
2979 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002980 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002981 return false;
2982 }
2983 }
2984 if (expectedNumCoords != numCoords)
2985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002986 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002987 return false;
2988 }
2989
2990 return true;
2991}
2992
2993bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2994{
2995 if (!context->getExtensions().pathRendering)
2996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002997 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002998 return false;
2999 }
3000 if (!context->hasPath(path))
3001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003002 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003003 return false;
3004 }
3005
3006 switch (pname)
3007 {
3008 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3009 if (value < 0.0f)
3010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003011 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003012 return false;
3013 }
3014 break;
3015 case GL_PATH_END_CAPS_CHROMIUM:
3016 switch (static_cast<GLenum>(value))
3017 {
3018 case GL_FLAT_CHROMIUM:
3019 case GL_SQUARE_CHROMIUM:
3020 case GL_ROUND_CHROMIUM:
3021 break;
3022 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003023 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003024 return false;
3025 }
3026 break;
3027 case GL_PATH_JOIN_STYLE_CHROMIUM:
3028 switch (static_cast<GLenum>(value))
3029 {
3030 case GL_MITER_REVERT_CHROMIUM:
3031 case GL_BEVEL_CHROMIUM:
3032 case GL_ROUND_CHROMIUM:
3033 break;
3034 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003035 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003036 return false;
3037 }
3038 case GL_PATH_MITER_LIMIT_CHROMIUM:
3039 if (value < 0.0f)
3040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003041 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003042 return false;
3043 }
3044 break;
3045
3046 case GL_PATH_STROKE_BOUND_CHROMIUM:
3047 // no errors, only clamping.
3048 break;
3049
3050 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003051 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003052 return false;
3053 }
3054 return true;
3055}
3056
3057bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3058{
3059 if (!context->getExtensions().pathRendering)
3060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003061 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003062 return false;
3063 }
3064
3065 if (!context->hasPath(path))
3066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003067 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003068 return false;
3069 }
3070 if (!value)
3071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003072 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003073 return false;
3074 }
3075
3076 switch (pname)
3077 {
3078 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3079 case GL_PATH_END_CAPS_CHROMIUM:
3080 case GL_PATH_JOIN_STYLE_CHROMIUM:
3081 case GL_PATH_MITER_LIMIT_CHROMIUM:
3082 case GL_PATH_STROKE_BOUND_CHROMIUM:
3083 break;
3084
3085 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003086 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003087 return false;
3088 }
3089
3090 return true;
3091}
3092
3093bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3094{
3095 if (!context->getExtensions().pathRendering)
3096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003097 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003098 return false;
3099 }
3100
3101 switch (func)
3102 {
3103 case GL_NEVER:
3104 case GL_ALWAYS:
3105 case GL_LESS:
3106 case GL_LEQUAL:
3107 case GL_EQUAL:
3108 case GL_GEQUAL:
3109 case GL_GREATER:
3110 case GL_NOTEQUAL:
3111 break;
3112 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003113 context->handleError(InvalidEnum() << "Invalid stencil function.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003114 return false;
3115 }
3116
3117 return true;
3118}
3119
3120// Note that the spec specifies that for the path drawing commands
3121// if the path object is not an existing path object the command
3122// does nothing and no error is generated.
3123// However if the path object exists but has not been specified any
3124// commands then an error is generated.
3125
3126bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3127{
3128 if (!context->getExtensions().pathRendering)
3129 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003130 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003131 return false;
3132 }
3133 if (context->hasPath(path) && !context->hasPathData(path))
3134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003135 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003136 return false;
3137 }
3138
3139 switch (fillMode)
3140 {
3141 case GL_COUNT_UP_CHROMIUM:
3142 case GL_COUNT_DOWN_CHROMIUM:
3143 break;
3144 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003145 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003146 return false;
3147 }
3148
3149 if (!isPow2(mask + 1))
3150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003151 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003152 return false;
3153 }
3154
3155 return true;
3156}
3157
3158bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3159{
3160 if (!context->getExtensions().pathRendering)
3161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003162 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003163 return false;
3164 }
3165 if (context->hasPath(path) && !context->hasPathData(path))
3166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003167 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003168 return false;
3169 }
3170
3171 return true;
3172}
3173
3174bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3175{
3176 if (!context->getExtensions().pathRendering)
3177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003178 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003179 return false;
3180 }
3181 if (context->hasPath(path) && !context->hasPathData(path))
3182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003183 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003184 return false;
3185 }
3186
3187 switch (coverMode)
3188 {
3189 case GL_CONVEX_HULL_CHROMIUM:
3190 case GL_BOUNDING_BOX_CHROMIUM:
3191 break;
3192 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003193 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003194 return false;
3195 }
3196 return true;
3197}
3198
3199bool ValidateStencilThenCoverFillPath(Context *context,
3200 GLuint path,
3201 GLenum fillMode,
3202 GLuint mask,
3203 GLenum coverMode)
3204{
3205 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3206 ValidateCoverPath(context, path, coverMode);
3207}
3208
3209bool ValidateStencilThenCoverStrokePath(Context *context,
3210 GLuint path,
3211 GLint reference,
3212 GLuint mask,
3213 GLenum coverMode)
3214{
3215 return ValidateStencilStrokePath(context, path, reference, mask) &&
3216 ValidateCoverPath(context, path, coverMode);
3217}
3218
3219bool ValidateIsPath(Context *context)
3220{
3221 if (!context->getExtensions().pathRendering)
3222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003223 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003224 return false;
3225 }
3226 return true;
3227}
3228
Sami Väisänend59ca052016-06-21 16:10:00 +03003229bool ValidateCoverFillPathInstanced(Context *context,
3230 GLsizei numPaths,
3231 GLenum pathNameType,
3232 const void *paths,
3233 GLuint pathBase,
3234 GLenum coverMode,
3235 GLenum transformType,
3236 const GLfloat *transformValues)
3237{
3238 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3239 transformType, transformValues))
3240 return false;
3241
3242 switch (coverMode)
3243 {
3244 case GL_CONVEX_HULL_CHROMIUM:
3245 case GL_BOUNDING_BOX_CHROMIUM:
3246 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3247 break;
3248 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003249 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003250 return false;
3251 }
3252
3253 return true;
3254}
3255
3256bool ValidateCoverStrokePathInstanced(Context *context,
3257 GLsizei numPaths,
3258 GLenum pathNameType,
3259 const void *paths,
3260 GLuint pathBase,
3261 GLenum coverMode,
3262 GLenum transformType,
3263 const GLfloat *transformValues)
3264{
3265 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3266 transformType, transformValues))
3267 return false;
3268
3269 switch (coverMode)
3270 {
3271 case GL_CONVEX_HULL_CHROMIUM:
3272 case GL_BOUNDING_BOX_CHROMIUM:
3273 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3274 break;
3275 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003276 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003277 return false;
3278 }
3279
3280 return true;
3281}
3282
3283bool ValidateStencilFillPathInstanced(Context *context,
3284 GLsizei numPaths,
3285 GLenum pathNameType,
3286 const void *paths,
3287 GLuint pathBase,
3288 GLenum fillMode,
3289 GLuint mask,
3290 GLenum transformType,
3291 const GLfloat *transformValues)
3292{
3293
3294 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3295 transformType, transformValues))
3296 return false;
3297
3298 switch (fillMode)
3299 {
3300 case GL_COUNT_UP_CHROMIUM:
3301 case GL_COUNT_DOWN_CHROMIUM:
3302 break;
3303 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003304 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003305 return false;
3306 }
3307 if (!isPow2(mask + 1))
3308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003309 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003310 return false;
3311 }
3312 return true;
3313}
3314
3315bool ValidateStencilStrokePathInstanced(Context *context,
3316 GLsizei numPaths,
3317 GLenum pathNameType,
3318 const void *paths,
3319 GLuint pathBase,
3320 GLint reference,
3321 GLuint mask,
3322 GLenum transformType,
3323 const GLfloat *transformValues)
3324{
3325 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3326 transformType, transformValues))
3327 return false;
3328
3329 // no more validation here.
3330
3331 return true;
3332}
3333
3334bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3335 GLsizei numPaths,
3336 GLenum pathNameType,
3337 const void *paths,
3338 GLuint pathBase,
3339 GLenum fillMode,
3340 GLuint mask,
3341 GLenum coverMode,
3342 GLenum transformType,
3343 const GLfloat *transformValues)
3344{
3345 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3346 transformType, transformValues))
3347 return false;
3348
3349 switch (coverMode)
3350 {
3351 case GL_CONVEX_HULL_CHROMIUM:
3352 case GL_BOUNDING_BOX_CHROMIUM:
3353 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3354 break;
3355 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003356 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003357 return false;
3358 }
3359
3360 switch (fillMode)
3361 {
3362 case GL_COUNT_UP_CHROMIUM:
3363 case GL_COUNT_DOWN_CHROMIUM:
3364 break;
3365 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003367 return false;
3368 }
3369 if (!isPow2(mask + 1))
3370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003372 return false;
3373 }
3374
3375 return true;
3376}
3377
3378bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3379 GLsizei numPaths,
3380 GLenum pathNameType,
3381 const void *paths,
3382 GLuint pathBase,
3383 GLint reference,
3384 GLuint mask,
3385 GLenum coverMode,
3386 GLenum transformType,
3387 const GLfloat *transformValues)
3388{
3389 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3390 transformType, transformValues))
3391 return false;
3392
3393 switch (coverMode)
3394 {
3395 case GL_CONVEX_HULL_CHROMIUM:
3396 case GL_BOUNDING_BOX_CHROMIUM:
3397 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3398 break;
3399 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003400 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003401 return false;
3402 }
3403
3404 return true;
3405}
3406
Sami Väisänen46eaa942016-06-29 10:26:37 +03003407bool ValidateBindFragmentInputLocation(Context *context,
3408 GLuint program,
3409 GLint location,
3410 const GLchar *name)
3411{
3412 if (!context->getExtensions().pathRendering)
3413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003414 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003415 return false;
3416 }
3417
3418 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3419 if (location >= MaxLocation)
3420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003421 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003422 return false;
3423 }
3424
3425 const auto *programObject = context->getProgram(program);
3426 if (!programObject)
3427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003428 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003429 return false;
3430 }
3431
3432 if (!name)
3433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003434 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003435 return false;
3436 }
3437
3438 if (angle::BeginsWith(name, "gl_"))
3439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003440 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003441 return false;
3442 }
3443
3444 return true;
3445}
3446
3447bool ValidateProgramPathFragmentInputGen(Context *context,
3448 GLuint program,
3449 GLint location,
3450 GLenum genMode,
3451 GLint components,
3452 const GLfloat *coeffs)
3453{
3454 if (!context->getExtensions().pathRendering)
3455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003456 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003457 return false;
3458 }
3459
3460 const auto *programObject = context->getProgram(program);
3461 if (!programObject || programObject->isFlaggedForDeletion())
3462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003464 return false;
3465 }
3466
3467 if (!programObject->isLinked())
3468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003469 context->handleError(InvalidOperation() << "Program is not linked.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003470 return false;
3471 }
3472
3473 switch (genMode)
3474 {
3475 case GL_NONE:
3476 if (components != 0)
3477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003478 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003479 return false;
3480 }
3481 break;
3482
3483 case GL_OBJECT_LINEAR_CHROMIUM:
3484 case GL_EYE_LINEAR_CHROMIUM:
3485 case GL_CONSTANT_CHROMIUM:
3486 if (components < 1 || components > 4)
3487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003488 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003489 return false;
3490 }
3491 if (!coeffs)
3492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003493 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003494 return false;
3495 }
3496 break;
3497
3498 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003499 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003500 return false;
3501 }
3502
3503 // If the location is -1 then the command is silently ignored
3504 // and no further validation is needed.
3505 if (location == -1)
3506 return true;
3507
Jamie Madillbd044ed2017-06-05 12:59:21 -04003508 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003509
3510 if (!binding.valid)
3511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003512 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003513 return false;
3514 }
3515
3516 if (binding.type != GL_NONE)
3517 {
3518 GLint expectedComponents = 0;
3519 switch (binding.type)
3520 {
3521 case GL_FLOAT:
3522 expectedComponents = 1;
3523 break;
3524 case GL_FLOAT_VEC2:
3525 expectedComponents = 2;
3526 break;
3527 case GL_FLOAT_VEC3:
3528 expectedComponents = 3;
3529 break;
3530 case GL_FLOAT_VEC4:
3531 expectedComponents = 4;
3532 break;
3533 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003534 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003535 InvalidOperation()
3536 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003537 return false;
3538 }
3539 if (expectedComponents != components && genMode != GL_NONE)
3540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003541 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003542 return false;
3543 }
3544 }
3545 return true;
3546}
3547
Geoff Lang97073d12016-04-20 10:42:34 -07003548bool ValidateCopyTextureCHROMIUM(Context *context,
3549 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003550 GLint sourceLevel,
3551 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003552 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003553 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003554 GLint internalFormat,
3555 GLenum destType,
3556 GLboolean unpackFlipY,
3557 GLboolean unpackPremultiplyAlpha,
3558 GLboolean unpackUnmultiplyAlpha)
3559{
3560 if (!context->getExtensions().copyTexture)
3561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003562 context->handleError(InvalidOperation()
3563 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003564 return false;
3565 }
3566
Geoff Lang4f0e0032017-05-01 16:04:35 -04003567 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003568 if (source == nullptr)
3569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003570 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003571 return false;
3572 }
3573
3574 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003577 return false;
3578 }
3579
3580 GLenum sourceTarget = source->getTarget();
3581 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003582
3583 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003585 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003586 return false;
3587 }
3588
Geoff Lang4f0e0032017-05-01 16:04:35 -04003589 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3590 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3591 if (sourceWidth == 0 || sourceHeight == 0)
3592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003593 context->handleError(InvalidValue()
3594 << "The source level of the source texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003595 return false;
3596 }
3597
3598 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3599 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003601 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003602 return false;
3603 }
3604
Geoff Lang4f0e0032017-05-01 16:04:35 -04003605 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003606 if (dest == nullptr)
3607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003608 context->handleError(InvalidValue()
3609 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003610 return false;
3611 }
3612
Geoff Lang4f0e0032017-05-01 16:04:35 -04003613 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003615 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003616 return false;
3617 }
3618
Geoff Lang4f0e0032017-05-01 16:04:35 -04003619 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3620 sourceHeight))
3621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003623 return false;
3624 }
3625
Geoff Lang97073d12016-04-20 10:42:34 -07003626 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidOperation()
3629 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003630 return false;
3631 }
3632
Geoff Lang4f0e0032017-05-01 16:04:35 -04003633 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003635 context->handleError(
3636 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003637 return false;
3638 }
3639
Geoff Lang97073d12016-04-20 10:42:34 -07003640 if (dest->getImmutableFormat())
3641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003642 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003643 return false;
3644 }
3645
3646 return true;
3647}
3648
3649bool ValidateCopySubTextureCHROMIUM(Context *context,
3650 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003651 GLint sourceLevel,
3652 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003653 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003654 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003655 GLint xoffset,
3656 GLint yoffset,
3657 GLint x,
3658 GLint y,
3659 GLsizei width,
3660 GLsizei height,
3661 GLboolean unpackFlipY,
3662 GLboolean unpackPremultiplyAlpha,
3663 GLboolean unpackUnmultiplyAlpha)
3664{
3665 if (!context->getExtensions().copyTexture)
3666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003667 context->handleError(InvalidOperation()
3668 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003669 return false;
3670 }
3671
Geoff Lang4f0e0032017-05-01 16:04:35 -04003672 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003673 if (source == nullptr)
3674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003675 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003676 return false;
3677 }
3678
3679 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003681 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003682 return false;
3683 }
3684
3685 GLenum sourceTarget = source->getTarget();
3686 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003687
3688 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003690 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003691 return false;
3692 }
3693
3694 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3695 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003697 context->handleError(InvalidValue()
3698 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003699 return false;
3700 }
3701
3702 if (x < 0 || y < 0)
3703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003704 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003705 return false;
3706 }
3707
3708 if (width < 0 || height < 0)
3709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003710 context->handleError(InvalidValue() << "width and height cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003711 return false;
3712 }
3713
Geoff Lang4f0e0032017-05-01 16:04:35 -04003714 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3715 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003717 context->handleError(InvalidValue() << "Source texture not large enough to copy from.");
Geoff Lang97073d12016-04-20 10:42:34 -07003718 return false;
3719 }
3720
Geoff Lang4f0e0032017-05-01 16:04:35 -04003721 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3722 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003724 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003725 return false;
3726 }
3727
Geoff Lang4f0e0032017-05-01 16:04:35 -04003728 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003729 if (dest == nullptr)
3730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 context->handleError(InvalidValue()
3732 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003733 return false;
3734 }
3735
Geoff Lang4f0e0032017-05-01 16:04:35 -04003736 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003738 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003739 return false;
3740 }
3741
Geoff Lang4f0e0032017-05-01 16:04:35 -04003742 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003744 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003745 return false;
3746 }
3747
Geoff Lang4f0e0032017-05-01 16:04:35 -04003748 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003750 context->handleError(
3751 InvalidValue() << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003752 return false;
3753 }
3754
3755 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3756 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003758 context->handleError(InvalidOperation()
3759 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003760 return false;
3761 }
3762
3763 if (xoffset < 0 || yoffset < 0)
3764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidValue() << "xoffset and yoffset cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003766 return false;
3767 }
3768
Geoff Lang4f0e0032017-05-01 16:04:35 -04003769 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3770 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003772 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003773 return false;
3774 }
3775
3776 return true;
3777}
3778
Geoff Lang47110bf2016-04-20 11:13:22 -07003779bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3780{
3781 if (!context->getExtensions().copyCompressedTexture)
3782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003783 context->handleError(InvalidOperation()
3784 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003785 return false;
3786 }
3787
3788 const gl::Texture *source = context->getTexture(sourceId);
3789 if (source == nullptr)
3790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003791 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003792 return false;
3793 }
3794
3795 if (source->getTarget() != GL_TEXTURE_2D)
3796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003797 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003798 return false;
3799 }
3800
3801 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003804 return false;
3805 }
3806
3807 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3808 if (!sourceFormat.info->compressed)
3809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidOperation()
3811 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003812 return false;
3813 }
3814
3815 const gl::Texture *dest = context->getTexture(destId);
3816 if (dest == nullptr)
3817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003818 context->handleError(InvalidValue()
3819 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003820 return false;
3821 }
3822
3823 if (dest->getTarget() != GL_TEXTURE_2D)
3824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003825 context->handleError(InvalidValue()
3826 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003827 return false;
3828 }
3829
3830 if (dest->getImmutableFormat())
3831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003832 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003833 return false;
3834 }
3835
3836 return true;
3837}
3838
Martin Radev4c4c8e72016-08-04 12:25:34 +03003839bool ValidateCreateShader(Context *context, GLenum type)
3840{
3841 switch (type)
3842 {
3843 case GL_VERTEX_SHADER:
3844 case GL_FRAGMENT_SHADER:
3845 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003846
Martin Radev4c4c8e72016-08-04 12:25:34 +03003847 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003848 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003850 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003851 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003852 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003853 break;
3854
Martin Radev4c4c8e72016-08-04 12:25:34 +03003855 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003856 context->handleError(InvalidEnum() << "Unknown shader type.");
Martin Radev4c4c8e72016-08-04 12:25:34 +03003857 return false;
3858 }
Jamie Madill29639852016-09-02 15:00:09 -04003859
3860 return true;
3861}
3862
3863bool ValidateBufferData(ValidationContext *context,
3864 GLenum target,
3865 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003866 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003867 GLenum usage)
3868{
3869 if (size < 0)
3870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003871 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003872 return false;
3873 }
3874
3875 switch (usage)
3876 {
3877 case GL_STREAM_DRAW:
3878 case GL_STATIC_DRAW:
3879 case GL_DYNAMIC_DRAW:
3880 break;
3881
3882 case GL_STREAM_READ:
3883 case GL_STREAM_COPY:
3884 case GL_STATIC_READ:
3885 case GL_STATIC_COPY:
3886 case GL_DYNAMIC_READ:
3887 case GL_DYNAMIC_COPY:
3888 if (context->getClientMajorVersion() < 3)
3889 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003890 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003891 return false;
3892 }
3893 break;
3894
3895 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003896 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003897 return false;
3898 }
3899
3900 if (!ValidBufferTarget(context, target))
3901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003902 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003903 return false;
3904 }
3905
3906 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3907
3908 if (!buffer)
3909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003910 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003911 return false;
3912 }
3913
3914 return true;
3915}
3916
3917bool ValidateBufferSubData(ValidationContext *context,
3918 GLenum target,
3919 GLintptr offset,
3920 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003921 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003922{
3923 if (size < 0 || offset < 0)
3924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003925 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003926 return false;
3927 }
3928
3929 if (!ValidBufferTarget(context, target))
3930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003931 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003932 return false;
3933 }
3934
3935 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3936
3937 if (!buffer)
3938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003939 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003940 return false;
3941 }
3942
3943 if (buffer->isMapped())
3944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003945 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003946 return false;
3947 }
3948
3949 // Check for possible overflow of size + offset
3950 angle::CheckedNumeric<size_t> checkedSize(size);
3951 checkedSize += offset;
3952 if (!checkedSize.IsValid())
3953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003954 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04003955 return false;
3956 }
3957
3958 if (size + offset > buffer->getSize())
3959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003960 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003961 return false;
3962 }
3963
Martin Radev4c4c8e72016-08-04 12:25:34 +03003964 return true;
3965}
3966
Geoff Langc339c4e2016-11-29 10:37:36 -05003967bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003968{
Geoff Langc339c4e2016-11-29 10:37:36 -05003969 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003971 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04003972 return false;
3973 }
3974
3975 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3976 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003977 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003979 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04003980 return false;
3981 }
3982
3983 return true;
3984}
3985
Jamie Madillef300b12016-10-07 15:12:09 -04003986bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3987{
3988 if (texture < GL_TEXTURE0 ||
3989 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003991 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04003992 return false;
3993 }
3994
3995 return true;
3996}
3997
3998bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3999{
4000 Program *programObject = GetValidProgram(context, program);
4001 if (!programObject)
4002 {
4003 return false;
4004 }
4005
4006 Shader *shaderObject = GetValidShader(context, shader);
4007 if (!shaderObject)
4008 {
4009 return false;
4010 }
4011
4012 switch (shaderObject->getType())
4013 {
4014 case GL_VERTEX_SHADER:
4015 {
4016 if (programObject->getAttachedVertexShader())
4017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004018 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004019 return false;
4020 }
4021 break;
4022 }
4023 case GL_FRAGMENT_SHADER:
4024 {
4025 if (programObject->getAttachedFragmentShader())
4026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004028 return false;
4029 }
4030 break;
4031 }
4032 case GL_COMPUTE_SHADER:
4033 {
4034 if (programObject->getAttachedComputeShader())
4035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004036 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004037 return false;
4038 }
4039 break;
4040 }
4041 default:
4042 UNREACHABLE();
4043 break;
4044 }
4045
4046 return true;
4047}
4048
Jamie Madill01a80ee2016-11-07 12:06:18 -05004049bool ValidateBindAttribLocation(ValidationContext *context,
4050 GLuint program,
4051 GLuint index,
4052 const GLchar *name)
4053{
4054 if (index >= MAX_VERTEX_ATTRIBS)
4055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004056 context->handleError(InvalidValue() << "Index exceeds MAX_VERTEX_ATTRIBS");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004057 return false;
4058 }
4059
4060 if (strncmp(name, "gl_", 3) == 0)
4061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidOperation() << "Cannot Bind built-in attributes");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004063 return false;
4064 }
4065
Geoff Langfc32e8b2017-05-31 14:16:59 -04004066 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4067 // shader-related entry points
4068 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004070 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004071 return false;
4072 }
4073
Jamie Madill01a80ee2016-11-07 12:06:18 -05004074 return GetValidProgram(context, program) != nullptr;
4075}
4076
4077bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4078{
4079 if (!ValidBufferTarget(context, target))
4080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004081 context->handleError(InvalidEnum() << "Invalid Buffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004082 return false;
4083 }
4084
4085 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4086 !context->isBufferGenerated(buffer))
4087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004088 context->handleError(InvalidOperation() << "Buffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004089 return false;
4090 }
4091
4092 return true;
4093}
4094
4095bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4096{
4097 if (!ValidFramebufferTarget(target))
4098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004099 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004100 return false;
4101 }
4102
4103 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4104 !context->isFramebufferGenerated(framebuffer))
4105 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004106 context->handleError(InvalidOperation() << "Framebuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004107 return false;
4108 }
4109
4110 return true;
4111}
4112
4113bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4114{
4115 if (target != GL_RENDERBUFFER)
4116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004117 context->handleError(InvalidEnum() << "Invalid Renderbuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004118 return false;
4119 }
4120
4121 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4122 !context->isRenderbufferGenerated(renderbuffer))
4123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004124 context->handleError(InvalidOperation() << "Renderbuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004125 return false;
4126 }
4127
4128 return true;
4129}
4130
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004131static bool ValidBlendEquationMode(GLenum mode)
4132{
4133 switch (mode)
4134 {
4135 case GL_FUNC_ADD:
4136 case GL_FUNC_SUBTRACT:
4137 case GL_FUNC_REVERSE_SUBTRACT:
4138 case GL_MIN:
4139 case GL_MAX:
4140 return true;
4141
4142 default:
4143 return false;
4144 }
4145}
4146
Jamie Madillc1d770e2017-04-13 17:31:24 -04004147bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004148 GLfloat red,
4149 GLfloat green,
4150 GLfloat blue,
4151 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004152{
4153 return true;
4154}
4155
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004156bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4157{
4158 if (!ValidBlendEquationMode(mode))
4159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004160 context->handleError(InvalidEnum() << "Invalid blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004161 return false;
4162 }
4163
4164 return true;
4165}
4166
4167bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4168{
4169 if (!ValidBlendEquationMode(modeRGB))
4170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004171 context->handleError(InvalidEnum() << "Invalid RGB blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004172 return false;
4173 }
4174
4175 if (!ValidBlendEquationMode(modeAlpha))
4176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004177 context->handleError(InvalidEnum() << "Invalid alpha blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004178 return false;
4179 }
4180
4181 return true;
4182}
4183
4184bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4185{
4186 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4187}
4188
4189static bool ValidSrcBlendFunc(GLenum srcBlend)
4190{
4191 switch (srcBlend)
4192 {
4193 case GL_ZERO:
4194 case GL_ONE:
4195 case GL_SRC_COLOR:
4196 case GL_ONE_MINUS_SRC_COLOR:
4197 case GL_DST_COLOR:
4198 case GL_ONE_MINUS_DST_COLOR:
4199 case GL_SRC_ALPHA:
4200 case GL_ONE_MINUS_SRC_ALPHA:
4201 case GL_DST_ALPHA:
4202 case GL_ONE_MINUS_DST_ALPHA:
4203 case GL_CONSTANT_COLOR:
4204 case GL_ONE_MINUS_CONSTANT_COLOR:
4205 case GL_CONSTANT_ALPHA:
4206 case GL_ONE_MINUS_CONSTANT_ALPHA:
4207 case GL_SRC_ALPHA_SATURATE:
4208 return true;
4209
4210 default:
4211 return false;
4212 }
4213}
4214
4215static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4216{
4217 switch (dstBlend)
4218 {
4219 case GL_ZERO:
4220 case GL_ONE:
4221 case GL_SRC_COLOR:
4222 case GL_ONE_MINUS_SRC_COLOR:
4223 case GL_DST_COLOR:
4224 case GL_ONE_MINUS_DST_COLOR:
4225 case GL_SRC_ALPHA:
4226 case GL_ONE_MINUS_SRC_ALPHA:
4227 case GL_DST_ALPHA:
4228 case GL_ONE_MINUS_DST_ALPHA:
4229 case GL_CONSTANT_COLOR:
4230 case GL_ONE_MINUS_CONSTANT_COLOR:
4231 case GL_CONSTANT_ALPHA:
4232 case GL_ONE_MINUS_CONSTANT_ALPHA:
4233 return true;
4234
4235 case GL_SRC_ALPHA_SATURATE:
4236 return (contextMajorVersion >= 3);
4237
4238 default:
4239 return false;
4240 }
4241}
4242
4243bool ValidateBlendFuncSeparate(ValidationContext *context,
4244 GLenum srcRGB,
4245 GLenum dstRGB,
4246 GLenum srcAlpha,
4247 GLenum dstAlpha)
4248{
4249 if (!ValidSrcBlendFunc(srcRGB))
4250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004251 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004252 return false;
4253 }
4254
4255 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
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 (!ValidSrcBlendFunc(srcAlpha))
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 (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
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
Frank Henigman146e8a12017-03-02 23:22:37 -05004273 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4274 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004275 {
4276 bool constantColorUsed =
4277 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4278 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4279
4280 bool constantAlphaUsed =
4281 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4282 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4283
4284 if (constantColorUsed && constantAlphaUsed)
4285 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004286 const char *msg;
4287 if (context->getExtensions().webglCompatibility)
4288 {
4289 msg =
4290 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4291 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4292 }
4293 else
4294 {
4295 msg =
4296 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4297 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4298 "implementation.";
4299 ERR() << msg;
4300 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004301 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004302 return false;
4303 }
4304 }
4305
4306 return true;
4307}
4308
Geoff Langc339c4e2016-11-29 10:37:36 -05004309bool ValidateGetString(Context *context, GLenum name)
4310{
4311 switch (name)
4312 {
4313 case GL_VENDOR:
4314 case GL_RENDERER:
4315 case GL_VERSION:
4316 case GL_SHADING_LANGUAGE_VERSION:
4317 case GL_EXTENSIONS:
4318 break;
4319
4320 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4321 if (!context->getExtensions().requestExtension)
4322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004323 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004324 return false;
4325 }
4326 break;
4327
4328 default:
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
4333 return true;
4334}
4335
Geoff Lang47c48082016-12-07 15:38:13 -05004336bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4337{
4338 if (width <= 0.0f || isNaN(width))
4339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004340 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004341 return false;
4342 }
4343
4344 return true;
4345}
4346
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004347bool ValidateVertexAttribPointer(ValidationContext *context,
4348 GLuint index,
4349 GLint size,
4350 GLenum type,
4351 GLboolean normalized,
4352 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004353 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004354{
Shao80957d92017-02-20 21:25:59 +08004355 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004356 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004357 return false;
4358 }
4359
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004360 if (stride < 0)
4361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004362 context->handleError(InvalidValue() << "stride cannot be negative.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004363 return false;
4364 }
4365
Shao80957d92017-02-20 21:25:59 +08004366 const Caps &caps = context->getCaps();
4367 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004368 {
Shao80957d92017-02-20 21:25:59 +08004369 if (stride > caps.maxVertexAttribStride)
4370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004371 context->handleError(InvalidValue()
4372 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004373 return false;
4374 }
4375
4376 if (index >= caps.maxVertexAttribBindings)
4377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004378 context->handleError(InvalidValue()
4379 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004380 return false;
4381 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004382 }
4383
4384 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4385 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4386 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4387 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004388 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4389 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004390 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004392 context
4393 ->handleError(InvalidOperation()
4394 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004395 return false;
4396 }
4397
4398 if (context->getExtensions().webglCompatibility)
4399 {
4400 // WebGL 1.0 [Section 6.14] Fixed point support
4401 // The WebGL API does not support the GL_FIXED data type.
4402 if (type == GL_FIXED)
4403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004404 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004405 return false;
4406 }
4407
Geoff Lang2d62ab72017-03-23 16:54:40 -04004408 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004409 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004410 return false;
4411 }
4412 }
4413
4414 return true;
4415}
4416
Jamie Madill876429b2017-04-20 15:46:24 -04004417bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004418{
4419 if (context->getExtensions().webglCompatibility && zNear > zFar)
4420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004421 context->handleError(InvalidOperation() << "Depth near > far.");
Frank Henigman6137ddc2017-02-10 18:55:07 -05004422 return false;
4423 }
4424
4425 return true;
4426}
4427
Jamie Madille8fb6402017-02-14 17:56:40 -05004428bool ValidateRenderbufferStorage(ValidationContext *context,
4429 GLenum target,
4430 GLenum internalformat,
4431 GLsizei width,
4432 GLsizei height)
4433{
4434 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4435 height);
4436}
4437
4438bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4439 GLenum target,
4440 GLsizei samples,
4441 GLenum internalformat,
4442 GLsizei width,
4443 GLsizei height)
4444{
4445 if (!context->getExtensions().framebufferMultisample)
4446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004447 context->handleError(InvalidOperation()
4448 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004449 return false;
4450 }
4451
4452 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4453 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4454 // generated.
4455 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004457 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004458 return false;
4459 }
4460
4461 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4462 // the specified storage. This is different than ES 3.0 in which a sample number higher
4463 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4464 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4465 if (context->getClientMajorVersion() >= 3)
4466 {
4467 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4468 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004470 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004471 return false;
4472 }
4473 }
4474
4475 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4476 width, height);
4477}
4478
Jamie Madillc1d770e2017-04-13 17:31:24 -04004479bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4480{
4481 if (!ValidFramebufferTarget(target))
4482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004483 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004484 return false;
4485 }
4486
4487 return true;
4488}
4489
4490bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004491 GLfloat red,
4492 GLfloat green,
4493 GLfloat blue,
4494 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004495{
4496 return true;
4497}
4498
Jamie Madill876429b2017-04-20 15:46:24 -04004499bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004500{
4501 return true;
4502}
4503
4504bool ValidateClearStencil(ValidationContext *context, GLint s)
4505{
4506 return true;
4507}
4508
4509bool ValidateColorMask(ValidationContext *context,
4510 GLboolean red,
4511 GLboolean green,
4512 GLboolean blue,
4513 GLboolean alpha)
4514{
4515 return true;
4516}
4517
4518bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4519{
4520 return true;
4521}
4522
4523bool ValidateCreateProgram(ValidationContext *context)
4524{
4525 return true;
4526}
4527
4528bool ValidateCullFace(ValidationContext *context, GLenum mode)
4529{
4530 switch (mode)
4531 {
4532 case GL_FRONT:
4533 case GL_BACK:
4534 case GL_FRONT_AND_BACK:
4535 break;
4536
4537 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004538 context->handleError(InvalidEnum() << "Invalid cull face parameter");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004539 return false;
4540 }
4541
4542 return true;
4543}
4544
4545bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4546{
4547 if (program == 0)
4548 {
4549 return false;
4550 }
4551
4552 if (!context->getProgram(program))
4553 {
4554 if (context->getShader(program))
4555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004556 context->handleError(InvalidOperation() << "Shader handle passed to DeleteProgram");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004557 return false;
4558 }
4559 else
4560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004561 context->handleError(InvalidValue() << "Invalid program handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004562 return false;
4563 }
4564 }
4565
4566 return true;
4567}
4568
4569bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4570{
4571 if (shader == 0)
4572 {
4573 return false;
4574 }
4575
4576 if (!context->getShader(shader))
4577 {
4578 if (context->getProgram(shader))
4579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004580 context->handleError(InvalidOperation() << "Program handle passed to DeleteShader");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004581 return false;
4582 }
4583 else
4584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004585 context->handleError(InvalidValue() << "Invalid shader handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004586 return false;
4587 }
4588 }
4589
4590 return true;
4591}
4592
4593bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4594{
4595 switch (func)
4596 {
4597 case GL_NEVER:
4598 case GL_ALWAYS:
4599 case GL_LESS:
4600 case GL_LEQUAL:
4601 case GL_EQUAL:
4602 case GL_GREATER:
4603 case GL_GEQUAL:
4604 case GL_NOTEQUAL:
4605 break;
4606
4607 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004608 context->handleError(InvalidEnum() << "Invalid depth function");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004609 return false;
4610 }
4611
4612 return true;
4613}
4614
4615bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4616{
4617 return true;
4618}
4619
4620bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4621{
4622 Program *programObject = GetValidProgram(context, program);
4623 if (!programObject)
4624 {
4625 return false;
4626 }
4627
4628 Shader *shaderObject = GetValidShader(context, shader);
4629 if (!shaderObject)
4630 {
4631 return false;
4632 }
4633
4634 const Shader *attachedShader = nullptr;
4635
4636 switch (shaderObject->getType())
4637 {
4638 case GL_VERTEX_SHADER:
4639 {
4640 attachedShader = programObject->getAttachedVertexShader();
4641 break;
4642 }
4643 case GL_FRAGMENT_SHADER:
4644 {
4645 attachedShader = programObject->getAttachedFragmentShader();
4646 break;
4647 }
4648 case GL_COMPUTE_SHADER:
4649 {
4650 attachedShader = programObject->getAttachedComputeShader();
4651 break;
4652 }
4653 default:
4654 UNREACHABLE();
4655 return false;
4656 }
4657
4658 if (attachedShader != shaderObject)
4659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004660 context->handleError(InvalidOperation() << "Cannot detach non-attached shader.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004661 return false;
4662 }
4663
4664 return true;
4665}
4666
4667bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4668{
4669 if (index >= MAX_VERTEX_ATTRIBS)
4670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004671 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004672 return false;
4673 }
4674
4675 return true;
4676}
4677
4678bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4679{
4680 if (index >= MAX_VERTEX_ATTRIBS)
4681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004682 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004683 return false;
4684 }
4685
4686 return true;
4687}
4688
4689bool ValidateFinish(ValidationContext *context)
4690{
4691 return true;
4692}
4693
4694bool ValidateFlush(ValidationContext *context)
4695{
4696 return true;
4697}
4698
4699bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4700{
4701 switch (mode)
4702 {
4703 case GL_CW:
4704 case GL_CCW:
4705 break;
4706 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004707 context->handleError(InvalidEnum() << "Invalid mode for FrontFace");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004708 return false;
4709 }
4710
4711 return true;
4712}
4713
4714bool ValidateGetActiveAttrib(ValidationContext *context,
4715 GLuint program,
4716 GLuint index,
4717 GLsizei bufsize,
4718 GLsizei *length,
4719 GLint *size,
4720 GLenum *type,
4721 GLchar *name)
4722{
4723 if (bufsize < 0)
4724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004725 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004726 return false;
4727 }
4728
4729 Program *programObject = GetValidProgram(context, program);
4730
4731 if (!programObject)
4732 {
4733 return false;
4734 }
4735
4736 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004738 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004739 return false;
4740 }
4741
4742 return true;
4743}
4744
4745bool ValidateGetActiveUniform(ValidationContext *context,
4746 GLuint program,
4747 GLuint index,
4748 GLsizei bufsize,
4749 GLsizei *length,
4750 GLint *size,
4751 GLenum *type,
4752 GLchar *name)
4753{
4754 if (bufsize < 0)
4755 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004756 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004757 return false;
4758 }
4759
4760 Program *programObject = GetValidProgram(context, program);
4761
4762 if (!programObject)
4763 {
4764 return false;
4765 }
4766
4767 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004769 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004770 return false;
4771 }
4772
4773 return true;
4774}
4775
4776bool ValidateGetAttachedShaders(ValidationContext *context,
4777 GLuint program,
4778 GLsizei maxcount,
4779 GLsizei *count,
4780 GLuint *shaders)
4781{
4782 if (maxcount < 0)
4783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004784 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004785 return false;
4786 }
4787
4788 Program *programObject = GetValidProgram(context, program);
4789
4790 if (!programObject)
4791 {
4792 return false;
4793 }
4794
4795 return true;
4796}
4797
4798bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4799{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004800 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4801 // shader-related entry points
4802 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004804 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004805 return false;
4806 }
4807
Jamie Madillc1d770e2017-04-13 17:31:24 -04004808 Program *programObject = GetValidProgram(context, program);
4809
4810 if (!programObject)
4811 {
4812 return false;
4813 }
4814
4815 if (!programObject->isLinked())
4816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004817 context->handleError(InvalidOperation() << "program not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004818 return false;
4819 }
4820
4821 return true;
4822}
4823
4824bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4825{
4826 GLenum nativeType;
4827 unsigned int numParams = 0;
4828 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4829}
4830
4831bool ValidateGetError(ValidationContext *context)
4832{
4833 return true;
4834}
4835
4836bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4837{
4838 GLenum nativeType;
4839 unsigned int numParams = 0;
4840 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4841}
4842
4843bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4844{
4845 GLenum nativeType;
4846 unsigned int numParams = 0;
4847 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4848}
4849
4850bool ValidateGetProgramInfoLog(ValidationContext *context,
4851 GLuint program,
4852 GLsizei bufsize,
4853 GLsizei *length,
4854 GLchar *infolog)
4855{
4856 if (bufsize < 0)
4857 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004858 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004859 return false;
4860 }
4861
4862 Program *programObject = GetValidProgram(context, program);
4863 if (!programObject)
4864 {
4865 return false;
4866 }
4867
4868 return true;
4869}
4870
4871bool ValidateGetShaderInfoLog(ValidationContext *context,
4872 GLuint shader,
4873 GLsizei bufsize,
4874 GLsizei *length,
4875 GLchar *infolog)
4876{
4877 if (bufsize < 0)
4878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004879 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004880 return false;
4881 }
4882
4883 Shader *shaderObject = GetValidShader(context, shader);
4884 if (!shaderObject)
4885 {
4886 return false;
4887 }
4888
4889 return true;
4890}
4891
4892bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4893 GLenum shadertype,
4894 GLenum precisiontype,
4895 GLint *range,
4896 GLint *precision)
4897{
4898 switch (shadertype)
4899 {
4900 case GL_VERTEX_SHADER:
4901 case GL_FRAGMENT_SHADER:
4902 break;
4903 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004904 context->handleError(InvalidOperation()
4905 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004906 return false;
4907 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004908 context->handleError(InvalidEnum() << "invalid shader type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004909 return false;
4910 }
4911
4912 switch (precisiontype)
4913 {
4914 case GL_LOW_FLOAT:
4915 case GL_MEDIUM_FLOAT:
4916 case GL_HIGH_FLOAT:
4917 case GL_LOW_INT:
4918 case GL_MEDIUM_INT:
4919 case GL_HIGH_INT:
4920 break;
4921
4922 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004923 context->handleError(InvalidEnum() << "invalid precision type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004924 return false;
4925 }
4926
4927 return true;
4928}
4929
4930bool ValidateGetShaderSource(ValidationContext *context,
4931 GLuint shader,
4932 GLsizei bufsize,
4933 GLsizei *length,
4934 GLchar *source)
4935{
4936 if (bufsize < 0)
4937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004938 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004939 return false;
4940 }
4941
4942 Shader *shaderObject = GetValidShader(context, shader);
4943 if (!shaderObject)
4944 {
4945 return false;
4946 }
4947
4948 return true;
4949}
4950
4951bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4952{
4953 if (strstr(name, "gl_") == name)
4954 {
4955 return false;
4956 }
4957
Geoff Langfc32e8b2017-05-31 14:16:59 -04004958 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4959 // shader-related entry points
4960 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004962 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004963 return false;
4964 }
4965
Jamie Madillc1d770e2017-04-13 17:31:24 -04004966 Program *programObject = GetValidProgram(context, program);
4967
4968 if (!programObject)
4969 {
4970 return false;
4971 }
4972
4973 if (!programObject->isLinked())
4974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004975 context->handleError(InvalidOperation() << "program is not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004976 return false;
4977 }
4978
4979 return true;
4980}
4981
4982bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4983{
4984 switch (mode)
4985 {
4986 case GL_FASTEST:
4987 case GL_NICEST:
4988 case GL_DONT_CARE:
4989 break;
4990
4991 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004992 context->handleError(InvalidEnum() << "invalid hint mode.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004993 return false;
4994 }
4995
4996 switch (target)
4997 {
4998 case GL_GENERATE_MIPMAP_HINT:
4999 break;
5000
5001 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
5002 if (!context->getExtensions().standardDerivatives)
5003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005004 context->handleError(InvalidOperation()
5005 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005006 return false;
5007 }
5008 break;
5009
5010 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005011 context->handleError(InvalidEnum() << "invalid hint target.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005012 return false;
5013 }
5014
5015 return true;
5016}
5017
5018bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5019{
5020 return true;
5021}
5022
5023bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5024{
5025 return true;
5026}
5027
5028bool ValidateIsProgram(ValidationContext *context, GLuint program)
5029{
5030 return true;
5031}
5032
5033bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5034{
5035 return true;
5036}
5037
5038bool ValidateIsShader(ValidationContext *context, GLuint shader)
5039{
5040 return true;
5041}
5042
5043bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5044{
5045 return true;
5046}
5047
5048bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5049{
5050 if (context->getClientMajorVersion() < 3)
5051 {
5052 switch (pname)
5053 {
5054 case GL_UNPACK_IMAGE_HEIGHT:
5055 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005056 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005057 return false;
5058
5059 case GL_UNPACK_ROW_LENGTH:
5060 case GL_UNPACK_SKIP_ROWS:
5061 case GL_UNPACK_SKIP_PIXELS:
5062 if (!context->getExtensions().unpackSubimage)
5063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005064 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005065 return false;
5066 }
5067 break;
5068
5069 case GL_PACK_ROW_LENGTH:
5070 case GL_PACK_SKIP_ROWS:
5071 case GL_PACK_SKIP_PIXELS:
5072 if (!context->getExtensions().packSubimage)
5073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005074 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005075 return false;
5076 }
5077 break;
5078 }
5079 }
5080
5081 if (param < 0)
5082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005083 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005084 return false;
5085 }
5086
5087 switch (pname)
5088 {
5089 case GL_UNPACK_ALIGNMENT:
5090 if (param != 1 && param != 2 && param != 4 && param != 8)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005093 return false;
5094 }
5095 break;
5096
5097 case GL_PACK_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_REVERSE_ROW_ORDER_ANGLE:
5106 case GL_UNPACK_ROW_LENGTH:
5107 case GL_UNPACK_IMAGE_HEIGHT:
5108 case GL_UNPACK_SKIP_IMAGES:
5109 case GL_UNPACK_SKIP_ROWS:
5110 case GL_UNPACK_SKIP_PIXELS:
5111 case GL_PACK_ROW_LENGTH:
5112 case GL_PACK_SKIP_ROWS:
5113 case GL_PACK_SKIP_PIXELS:
5114 break;
5115
5116 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005117 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005118 return false;
5119 }
5120
5121 return true;
5122}
5123
5124bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5125{
5126 return true;
5127}
5128
5129bool ValidateReleaseShaderCompiler(ValidationContext *context)
5130{
5131 return true;
5132}
5133
Jamie Madill876429b2017-04-20 15:46:24 -04005134bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005135{
5136 return true;
5137}
5138
5139bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5140{
5141 if (width < 0 || height < 0)
5142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005143 context->handleError(InvalidValue() << "Scissor width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005144 return false;
5145 }
5146
5147 return true;
5148}
5149
5150bool ValidateShaderBinary(ValidationContext *context,
5151 GLsizei n,
5152 const GLuint *shaders,
5153 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005154 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005155 GLsizei length)
5156{
5157 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5158 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5159 shaderBinaryFormats.end())
5160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005161 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005162 return false;
5163 }
5164
5165 return true;
5166}
5167
5168bool ValidateShaderSource(ValidationContext *context,
5169 GLuint shader,
5170 GLsizei count,
5171 const GLchar *const *string,
5172 const GLint *length)
5173{
5174 if (count < 0)
5175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005176 context->handleError(InvalidValue() << "Count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005177 return false;
5178 }
5179
Geoff Langfc32e8b2017-05-31 14:16:59 -04005180 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5181 // shader-related entry points
5182 if (context->getExtensions().webglCompatibility)
5183 {
5184 for (GLsizei i = 0; i < count; i++)
5185 {
5186 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
5187 if (!IsValidESSLString(string[i], len))
5188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005189 context->handleError(InvalidValue() << "Shader source contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04005190 return false;
5191 }
5192 }
5193 }
5194
Jamie Madillc1d770e2017-04-13 17:31:24 -04005195 Shader *shaderObject = GetValidShader(context, shader);
5196 if (!shaderObject)
5197 {
5198 return false;
5199 }
5200
5201 return true;
5202}
5203
5204bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5205{
5206 if (!IsValidStencilFunc(func))
5207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005208 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005209 return false;
5210 }
5211
5212 return true;
5213}
5214
5215bool ValidateStencilFuncSeparate(ValidationContext *context,
5216 GLenum face,
5217 GLenum func,
5218 GLint ref,
5219 GLuint mask)
5220{
5221 if (!IsValidStencilFace(face))
5222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005223 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005224 return false;
5225 }
5226
5227 if (!IsValidStencilFunc(func))
5228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005229 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005230 return false;
5231 }
5232
5233 return true;
5234}
5235
5236bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5237{
5238 return true;
5239}
5240
5241bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5242{
5243 if (!IsValidStencilFace(face))
5244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005245 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005246 return false;
5247 }
5248
5249 return true;
5250}
5251
5252bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5253{
5254 if (!IsValidStencilOp(fail))
5255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005256 context->handleError(InvalidEnum() << "Invalid stencil fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005257 return false;
5258 }
5259
5260 if (!IsValidStencilOp(zfail))
5261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005262 context->handleError(InvalidEnum() << "Invalid stencil z fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005263 return false;
5264 }
5265
5266 if (!IsValidStencilOp(zpass))
5267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005268 context->handleError(InvalidEnum() << "Invalid stencil z pass op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005269 return false;
5270 }
5271
5272 return true;
5273}
5274
5275bool ValidateStencilOpSeparate(ValidationContext *context,
5276 GLenum face,
5277 GLenum fail,
5278 GLenum zfail,
5279 GLenum zpass)
5280{
5281 if (!IsValidStencilFace(face))
5282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005283 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005284 return false;
5285 }
5286
5287 return ValidateStencilOp(context, fail, zfail, zpass);
5288}
5289
5290bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5291{
5292 return ValidateUniform(context, GL_FLOAT, location, 1);
5293}
5294
5295bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5296{
5297 return ValidateUniform(context, GL_FLOAT, location, count);
5298}
5299
Jamie Madillbe849e42017-05-02 15:49:00 -04005300bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5301{
5302 return ValidateUniform1iv(context, location, 1, &x);
5303}
5304
Jamie Madillc1d770e2017-04-13 17:31:24 -04005305bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5306{
5307 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5308}
5309
5310bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5311{
5312 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5313}
5314
5315bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5316{
5317 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5318}
5319
5320bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5321{
5322 return ValidateUniform(context, GL_INT_VEC2, location, count);
5323}
5324
5325bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5326{
5327 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5328}
5329
5330bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5331{
5332 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5333}
5334
5335bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5336{
5337 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5338}
5339
5340bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5341{
5342 return ValidateUniform(context, GL_INT_VEC3, location, count);
5343}
5344
5345bool ValidateUniform4f(ValidationContext *context,
5346 GLint location,
5347 GLfloat x,
5348 GLfloat y,
5349 GLfloat z,
5350 GLfloat w)
5351{
5352 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5353}
5354
5355bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5356{
5357 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5358}
5359
5360bool ValidateUniform4i(ValidationContext *context,
5361 GLint location,
5362 GLint x,
5363 GLint y,
5364 GLint z,
5365 GLint w)
5366{
5367 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5368}
5369
5370bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5371{
5372 return ValidateUniform(context, GL_INT_VEC4, location, count);
5373}
5374
5375bool ValidateUniformMatrix2fv(ValidationContext *context,
5376 GLint location,
5377 GLsizei count,
5378 GLboolean transpose,
5379 const GLfloat *value)
5380{
5381 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5382}
5383
5384bool ValidateUniformMatrix3fv(ValidationContext *context,
5385 GLint location,
5386 GLsizei count,
5387 GLboolean transpose,
5388 const GLfloat *value)
5389{
5390 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5391}
5392
5393bool ValidateUniformMatrix4fv(ValidationContext *context,
5394 GLint location,
5395 GLsizei count,
5396 GLboolean transpose,
5397 const GLfloat *value)
5398{
5399 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5400}
5401
5402bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5403{
5404 Program *programObject = GetValidProgram(context, program);
5405
5406 if (!programObject)
5407 {
5408 return false;
5409 }
5410
5411 return true;
5412}
5413
5414bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5415{
5416 if (index >= MAX_VERTEX_ATTRIBS)
5417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005418 context->handleError(InvalidValue() << "Vertex attrib index out of range.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005419 return false;
5420 }
5421
5422 return true;
5423}
5424
5425bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5426{
5427 return ValidateVertexAttribIndex(context, index);
5428}
5429
5430bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5431{
5432 return ValidateVertexAttribIndex(context, index);
5433}
5434
5435bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5436{
5437 return ValidateVertexAttribIndex(context, index);
5438}
5439
5440bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5441{
5442 return ValidateVertexAttribIndex(context, index);
5443}
5444
5445bool ValidateVertexAttrib3f(ValidationContext *context,
5446 GLuint index,
5447 GLfloat x,
5448 GLfloat y,
5449 GLfloat z)
5450{
5451 return ValidateVertexAttribIndex(context, index);
5452}
5453
5454bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5455{
5456 return ValidateVertexAttribIndex(context, index);
5457}
5458
5459bool ValidateVertexAttrib4f(ValidationContext *context,
5460 GLuint index,
5461 GLfloat x,
5462 GLfloat y,
5463 GLfloat z,
5464 GLfloat w)
5465{
5466 return ValidateVertexAttribIndex(context, index);
5467}
5468
5469bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5470{
5471 return ValidateVertexAttribIndex(context, index);
5472}
5473
5474bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5475{
5476 if (width < 0 || height < 0)
5477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005478 context->handleError(InvalidValue() << "Viewport width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005479 return false;
5480 }
5481
5482 return true;
5483}
5484
5485bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5486{
5487 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5488}
5489
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005490bool ValidateDrawElements(ValidationContext *context,
5491 GLenum mode,
5492 GLsizei count,
5493 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005494 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005495{
5496 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5497}
5498
Jamie Madillbe849e42017-05-02 15:49:00 -04005499bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5500 GLenum target,
5501 GLenum attachment,
5502 GLenum pname,
5503 GLint *params)
5504{
5505 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5506 nullptr);
5507}
5508
5509bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5510{
5511 return ValidateGetProgramivBase(context, program, pname, nullptr);
5512}
5513
5514bool ValidateCopyTexImage2D(ValidationContext *context,
5515 GLenum target,
5516 GLint level,
5517 GLenum internalformat,
5518 GLint x,
5519 GLint y,
5520 GLsizei width,
5521 GLsizei height,
5522 GLint border)
5523{
5524 if (context->getClientMajorVersion() < 3)
5525 {
5526 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5527 0, x, y, width, height, border);
5528 }
5529
5530 ASSERT(context->getClientMajorVersion() == 3);
5531 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5532 0, x, y, width, height, border);
5533}
5534
5535bool ValidateCopyTexSubImage2D(Context *context,
5536 GLenum target,
5537 GLint level,
5538 GLint xoffset,
5539 GLint yoffset,
5540 GLint x,
5541 GLint y,
5542 GLsizei width,
5543 GLsizei height)
5544{
5545 if (context->getClientMajorVersion() < 3)
5546 {
5547 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5548 yoffset, x, y, width, height, 0);
5549 }
5550
5551 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5552 yoffset, 0, x, y, width, height, 0);
5553}
5554
5555bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5556{
5557 return ValidateGenOrDelete(context, n);
5558}
5559
5560bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5561{
5562 return ValidateGenOrDelete(context, n);
5563}
5564
5565bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5566{
5567 return ValidateGenOrDelete(context, n);
5568}
5569
5570bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5571{
5572 return ValidateGenOrDelete(context, n);
5573}
5574
5575bool ValidateDisable(Context *context, GLenum cap)
5576{
5577 if (!ValidCap(context, cap, false))
5578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005579 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 return false;
5581 }
5582
5583 return true;
5584}
5585
5586bool ValidateEnable(Context *context, GLenum cap)
5587{
5588 if (!ValidCap(context, cap, false))
5589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005590 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005591 return false;
5592 }
5593
5594 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5595 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5596 {
5597 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005598 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005599
5600 // We also output an error message to the debugger window if tracing is active, so that
5601 // developers can see the error message.
5602 ERR() << errorMessage;
5603 return false;
5604 }
5605
5606 return true;
5607}
5608
5609bool ValidateFramebufferRenderbuffer(Context *context,
5610 GLenum target,
5611 GLenum attachment,
5612 GLenum renderbuffertarget,
5613 GLuint renderbuffer)
5614{
5615 if (!ValidFramebufferTarget(target) ||
5616 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005618 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005619 return false;
5620 }
5621
5622 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5623 renderbuffertarget, renderbuffer);
5624}
5625
5626bool ValidateFramebufferTexture2D(Context *context,
5627 GLenum target,
5628 GLenum attachment,
5629 GLenum textarget,
5630 GLuint texture,
5631 GLint level)
5632{
5633 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5634 // extension
5635 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5636 level != 0)
5637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005638 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005639 return false;
5640 }
5641
5642 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5643 {
5644 return false;
5645 }
5646
5647 if (texture != 0)
5648 {
5649 gl::Texture *tex = context->getTexture(texture);
5650 ASSERT(tex);
5651
5652 const gl::Caps &caps = context->getCaps();
5653
5654 switch (textarget)
5655 {
5656 case GL_TEXTURE_2D:
5657 {
5658 if (level > gl::log2(caps.max2DTextureSize))
5659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005660 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005661 return false;
5662 }
5663 if (tex->getTarget() != GL_TEXTURE_2D)
5664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005665 context->handleError(InvalidOperation()
5666 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 return false;
5668 }
5669 }
5670 break;
5671
5672 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5673 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5674 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5675 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5676 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5677 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5678 {
5679 if (level > gl::log2(caps.maxCubeMapTextureSize))
5680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005681 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 return false;
5683 }
5684 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005686 context->handleError(InvalidOperation()
5687 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005688 return false;
5689 }
5690 }
5691 break;
5692
5693 case GL_TEXTURE_2D_MULTISAMPLE:
5694 {
5695 if (context->getClientVersion() < ES_3_1)
5696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005697 context->handleError(InvalidOperation()
5698 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005699 return false;
5700 }
5701
5702 if (level != 0)
5703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005704 context->handleError(InvalidValue()
5705 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 return false;
5707 }
5708 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005710 context->handleError(InvalidOperation()
5711 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005712 return false;
5713 }
5714 }
5715 break;
5716
5717 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005718 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005719 return false;
5720 }
5721
5722 const Format &format = tex->getFormat(textarget, level);
5723 if (format.info->compressed)
5724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005725 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005726 return false;
5727 }
5728 }
5729
5730 return true;
5731}
5732
5733bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5734{
5735 return ValidateGenOrDelete(context, n);
5736}
5737
5738bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5739{
5740 return ValidateGenOrDelete(context, n);
5741}
5742
5743bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5744{
5745 return ValidateGenOrDelete(context, n);
5746}
5747
5748bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5749{
5750 return ValidateGenOrDelete(context, n);
5751}
5752
5753bool ValidateGenerateMipmap(Context *context, GLenum target)
5754{
5755 if (!ValidTextureTarget(context, target))
5756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005757 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 return false;
5759 }
5760
5761 Texture *texture = context->getTargetTexture(target);
5762
5763 if (texture == nullptr)
5764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005765 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005766 return false;
5767 }
5768
5769 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5770
5771 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5772 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5773 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
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 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5780 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5781 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5782
5783 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5784 // unsized formats or that are color renderable and filterable. Since we do not track if
5785 // the texture was created with sized or unsized format (only sized formats are stored),
5786 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5787 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5788 // textures since they're the only texture format that can be created with unsized formats
5789 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5790 // was the last version to use add them.
5791 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5792 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005794 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005795 return false;
5796 }
5797
Geoff Lang65ac5b92017-05-01 13:16:30 -04005798 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5799 bool supportsSRGBMipmapGeneration =
5800 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5801 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005803 context->handleError(InvalidOperation()
5804 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 return false;
5806 }
5807
5808 // Non-power of 2 ES2 check
5809 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5810 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5811 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5812 {
5813 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005814 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817
5818 // Cube completeness check
5819 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005821 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005822 return false;
5823 }
5824
5825 return true;
5826}
5827
5828bool ValidateGetBufferParameteriv(ValidationContext *context,
5829 GLenum target,
5830 GLenum pname,
5831 GLint *params)
5832{
5833 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5834}
5835
5836bool ValidateGetRenderbufferParameteriv(Context *context,
5837 GLenum target,
5838 GLenum pname,
5839 GLint *params)
5840{
5841 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5842}
5843
5844bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5845{
5846 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5847}
5848
5849bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5850{
5851 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5852}
5853
5854bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5855{
5856 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5857}
5858
5859bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5860{
5861 return ValidateGetUniformBase(context, program, location);
5862}
5863
5864bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5865{
5866 return ValidateGetUniformBase(context, program, location);
5867}
5868
5869bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5870{
5871 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5872}
5873
5874bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5875{
5876 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5877}
5878
5879bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5880{
5881 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5882}
5883
5884bool ValidateIsEnabled(Context *context, GLenum cap)
5885{
5886 if (!ValidCap(context, cap, true))
5887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005888 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005889 return false;
5890 }
5891
5892 return true;
5893}
5894
5895bool ValidateLinkProgram(Context *context, GLuint program)
5896{
5897 if (context->hasActiveTransformFeedback(program))
5898 {
5899 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005900 context->handleError(InvalidOperation() << "Cannot link program while program is "
5901 "associated with an active transform "
5902 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005903 return false;
5904 }
5905
5906 Program *programObject = GetValidProgram(context, program);
5907 if (!programObject)
5908 {
5909 return false;
5910 }
5911
5912 return true;
5913}
5914
5915bool ValidateReadPixels(ValidationContext *context,
5916 GLint x,
5917 GLint y,
5918 GLsizei width,
5919 GLsizei height,
5920 GLenum format,
5921 GLenum type,
5922 void *pixels)
5923{
5924 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5925 nullptr, pixels);
5926}
5927
5928bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5929{
5930 return ValidateTexParameterBase(context, target, pname, -1, &param);
5931}
5932
5933bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5934{
5935 return ValidateTexParameterBase(context, target, pname, -1, params);
5936}
5937
5938bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5939{
5940 return ValidateTexParameterBase(context, target, pname, -1, &param);
5941}
5942
5943bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5944{
5945 return ValidateTexParameterBase(context, target, pname, -1, params);
5946}
5947
5948bool ValidateUseProgram(Context *context, GLuint program)
5949{
5950 if (program != 0)
5951 {
5952 Program *programObject = context->getProgram(program);
5953 if (!programObject)
5954 {
5955 // ES 3.1.0 section 7.3 page 72
5956 if (context->getShader(program))
5957 {
5958 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005959 InvalidOperation()
5960 << "Attempted to use a single shader instead of a shader program.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005961 return false;
5962 }
5963 else
5964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005965 context->handleError(InvalidValue() << "Program invalid.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005966 return false;
5967 }
5968 }
5969 if (!programObject->isLinked())
5970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005971 context->handleError(InvalidOperation() << "Program not linked.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005972 return false;
5973 }
5974 }
5975 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5976 {
5977 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005978 context
5979 ->handleError(InvalidOperation()
5980 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005981 return false;
5982 }
5983
5984 return true;
5985}
5986
Jamie Madillc29968b2016-01-20 11:17:23 -05005987} // namespace gl