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