blob: dc3b49bdf00c2a5f21f15f0579da7fac5186027a [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
Jamie Madillef300b12016-10-07 15:12:09 -040017#include "libANGLE/Framebuffer.h"
18#include "libANGLE/FramebufferAttachment.h"
19#include "libANGLE/Renderbuffer.h"
20#include "libANGLE/Shader.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Texture.h"
Jamie Madillef300b12016-10-07 15:12:09 -040022#include "libANGLE/Uniform.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/VertexArray.h"
Jamie Madillef300b12016-10-07 15:12:09 -040024#include "libANGLE/formatutils.h"
25#include "libANGLE/validationES.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28namespace gl
29{
30
Jamie Madillc29968b2016-01-20 11:17:23 -050031namespace
32{
33
34bool IsPartialBlit(gl::Context *context,
35 const FramebufferAttachment *readBuffer,
36 const FramebufferAttachment *writeBuffer,
37 GLint srcX0,
38 GLint srcY0,
39 GLint srcX1,
40 GLint srcY1,
41 GLint dstX0,
42 GLint dstY0,
43 GLint dstX1,
44 GLint dstY1)
45{
46 const Extents &writeSize = writeBuffer->getSize();
47 const Extents &readSize = readBuffer->getSize();
48
49 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
50 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
51 {
52 return true;
53 }
54
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050056 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070057 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050058 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
59 scissor.height < writeSize.height;
60 }
61
62 return false;
63}
64
Sami Väisänend59ca052016-06-21 16:10:00 +030065template <typename T>
66bool ValidatePathInstances(gl::Context *context,
67 GLsizei numPaths,
68 const void *paths,
69 GLuint pathBase)
70{
71 const auto *array = static_cast<const T *>(paths);
72
73 for (GLsizei i = 0; i < numPaths; ++i)
74 {
75 const GLuint pathName = array[i] + pathBase;
76 if (context->hasPath(pathName) && !context->hasPathData(pathName))
77 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050078 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänend59ca052016-06-21 16:10:00 +030079 return false;
80 }
81 }
82 return true;
83}
84
85bool ValidateInstancedPathParameters(gl::Context *context,
86 GLsizei numPaths,
87 GLenum pathNameType,
88 const void *paths,
89 GLuint pathBase,
90 GLenum transformType,
91 const GLfloat *transformValues)
92{
93 if (!context->getExtensions().pathRendering)
94 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050095 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänend59ca052016-06-21 16:10:00 +030096 return false;
97 }
98
99 if (paths == nullptr)
100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500101 context->handleError(InvalidValue() << "No path name array.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300102 return false;
103 }
104
105 if (numPaths < 0)
106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500107 context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300108 return false;
109 }
110
111 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500113 context->handleError(InvalidOperation() << "Overflow in numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300114 return false;
115 }
116
117 std::uint32_t pathNameTypeSize = 0;
118 std::uint32_t componentCount = 0;
119
120 switch (pathNameType)
121 {
122 case GL_UNSIGNED_BYTE:
123 pathNameTypeSize = sizeof(GLubyte);
124 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
125 return false;
126 break;
127
128 case GL_BYTE:
129 pathNameTypeSize = sizeof(GLbyte);
130 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
131 return false;
132 break;
133
134 case GL_UNSIGNED_SHORT:
135 pathNameTypeSize = sizeof(GLushort);
136 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
137 return false;
138 break;
139
140 case GL_SHORT:
141 pathNameTypeSize = sizeof(GLshort);
142 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
143 return false;
144 break;
145
146 case GL_UNSIGNED_INT:
147 pathNameTypeSize = sizeof(GLuint);
148 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
149 return false;
150 break;
151
152 case GL_INT:
153 pathNameTypeSize = sizeof(GLint);
154 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
155 return false;
156 break;
157
158 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500159 context->handleError(InvalidEnum() << "Invalid path name type.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300160 return false;
161 }
162
163 switch (transformType)
164 {
165 case GL_NONE:
166 componentCount = 0;
167 break;
168 case GL_TRANSLATE_X_CHROMIUM:
169 case GL_TRANSLATE_Y_CHROMIUM:
170 componentCount = 1;
171 break;
172 case GL_TRANSLATE_2D_CHROMIUM:
173 componentCount = 2;
174 break;
175 case GL_TRANSLATE_3D_CHROMIUM:
176 componentCount = 3;
177 break;
178 case GL_AFFINE_2D_CHROMIUM:
179 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
180 componentCount = 6;
181 break;
182 case GL_AFFINE_3D_CHROMIUM:
183 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
184 componentCount = 12;
185 break;
186 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500187 context->handleError(InvalidEnum() << "Invalid transformation.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300188 return false;
189 }
190 if (componentCount != 0 && transformValues == nullptr)
191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500192 context->handleError(InvalidValue() << "No transform array given.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300193 return false;
194 }
195
196 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
197 checkedSize += (numPaths * pathNameTypeSize);
198 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
199 if (!checkedSize.IsValid())
200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500201 context->handleError(InvalidOperation() << "Overflow in num paths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300202 return false;
203 }
204
205 return true;
206}
207
Geoff Lang4f0e0032017-05-01 16:04:35 -0400208bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
Geoff Lang97073d12016-04-20 10:42:34 -0700209{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400210 // Table 1.1 from the CHROMIUM_copy_texture spec
Geoff Langca271392017-04-05 12:30:00 -0400211 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700212 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400213 case GL_RED:
Geoff Lang97073d12016-04-20 10:42:34 -0700214 case GL_ALPHA:
215 case GL_LUMINANCE:
216 case GL_LUMINANCE_ALPHA:
217 case GL_RGB:
218 case GL_RGBA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400219 case GL_RGB8:
220 case GL_RGBA8:
221 case GL_BGRA_EXT:
222 case GL_BGRA8_EXT:
Geoff Lang97073d12016-04-20 10:42:34 -0700223 return true;
224
Geoff Lang4f0e0032017-05-01 16:04:35 -0400225 default:
226 return false;
227 }
228}
Geoff Lang97073d12016-04-20 10:42:34 -0700229
Geoff Lang4f0e0032017-05-01 16:04:35 -0400230bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
231{
232 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
233}
234
235bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
236{
237 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
238}
239
240bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
241{
242 // Table 1.0 from the CHROMIUM_copy_texture spec
243 switch (internalFormat)
244 {
245 case GL_RGB:
246 case GL_RGBA:
247 case GL_RGB8:
248 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700249 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400250 case GL_BGRA8_EXT:
251 case GL_SRGB_EXT:
252 case GL_SRGB_ALPHA_EXT:
253 case GL_R8:
254 case GL_R8UI:
255 case GL_RG8:
256 case GL_RG8UI:
257 case GL_SRGB8:
258 case GL_RGB565:
259 case GL_RGB8UI:
260 case GL_SRGB8_ALPHA8:
261 case GL_RGB5_A1:
262 case GL_RGBA4:
263 case GL_RGBA8UI:
264 case GL_RGB9_E5:
265 case GL_R16F:
266 case GL_R32F:
267 case GL_RG16F:
268 case GL_RG32F:
269 case GL_RGB16F:
270 case GL_RGB32F:
271 case GL_RGBA16F:
272 case GL_RGBA32F:
273 case GL_R11F_G11F_B10F:
274 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700275
276 default:
277 return false;
278 }
279}
280
281bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
282{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400283 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700284 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400285 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700286 }
287
Geoff Lang4f0e0032017-05-01 16:04:35 -0400288 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
289 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700290 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400291 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700292 }
293
294 return true;
295}
296
Geoff Lang4f0e0032017-05-01 16:04:35 -0400297bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700298{
299 switch (target)
300 {
301 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400302 return textureType == GL_TEXTURE_2D;
303
304 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
305 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
306 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
307 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
308 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
309 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
310 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700311
312 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
313 // supported
314
315 default:
316 return false;
317 }
318}
319
320bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
321{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400322 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700323 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400324 case GL_TEXTURE_2D:
325 return true;
326
327 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
328 // supported
329
330 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
331 // supported
332
333 default:
334 return false;
335 }
336}
337
338bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
339{
340 if (level < 0)
341 {
342 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700343 }
344
Geoff Lang4f0e0032017-05-01 16:04:35 -0400345 if (level > 0 && context->getClientVersion() < ES_3_0)
346 {
347 return false;
348 }
Geoff Lang97073d12016-04-20 10:42:34 -0700349
Geoff Lang4f0e0032017-05-01 16:04:35 -0400350 return true;
351}
352
353bool IsValidCopyTextureDestinationLevel(Context *context,
354 GLenum target,
355 GLint level,
356 GLsizei width,
357 GLsizei height)
358{
359 if (level < 0)
360 {
361 return false;
362 }
363
364 if (level > 0 && context->getClientVersion() < ES_3_0)
365 {
366 return false;
367 }
368
369 const Caps &caps = context->getCaps();
370 if (target == GL_TEXTURE_2D)
371 {
372 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
373 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
374 {
375 return false;
376 }
377 }
378 else if (IsCubeMapTextureTarget(target))
379 {
380 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
381 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
382 {
383 return false;
384 }
385 }
386
387 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700388}
389
Jamie Madillc1d770e2017-04-13 17:31:24 -0400390bool IsValidStencilFunc(GLenum func)
391{
392 switch (func)
393 {
394 case GL_NEVER:
395 case GL_ALWAYS:
396 case GL_LESS:
397 case GL_LEQUAL:
398 case GL_EQUAL:
399 case GL_GEQUAL:
400 case GL_GREATER:
401 case GL_NOTEQUAL:
402 return true;
403
404 default:
405 return false;
406 }
407}
408
409bool IsValidStencilFace(GLenum face)
410{
411 switch (face)
412 {
413 case GL_FRONT:
414 case GL_BACK:
415 case GL_FRONT_AND_BACK:
416 return true;
417
418 default:
419 return false;
420 }
421}
422
423bool IsValidStencilOp(GLenum op)
424{
425 switch (op)
426 {
427 case GL_ZERO:
428 case GL_KEEP:
429 case GL_REPLACE:
430 case GL_INCR:
431 case GL_DECR:
432 case GL_INVERT:
433 case GL_INCR_WRAP:
434 case GL_DECR_WRAP:
435 return true;
436
437 default:
438 return false;
439 }
440}
441
Jamie Madillbe849e42017-05-02 15:49:00 -0400442bool ValidateES2CopyTexImageParameters(ValidationContext *context,
443 GLenum target,
444 GLint level,
445 GLenum internalformat,
446 bool isSubImage,
447 GLint xoffset,
448 GLint yoffset,
449 GLint x,
450 GLint y,
451 GLsizei width,
452 GLsizei height,
453 GLint border)
454{
455 if (!ValidTexture2DDestinationTarget(context, target))
456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500457 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -0400458 return false;
459 }
460
461 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500463 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400464 return false;
465 }
466
467 Format textureFormat = Format::Invalid();
468 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
469 xoffset, yoffset, 0, x, y, width, height, border,
470 &textureFormat))
471 {
472 return false;
473 }
474
475 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
476 GLenum colorbufferFormat =
477 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
478 const auto &formatInfo = *textureFormat.info;
479
480 // [OpenGL ES 2.0.24] table 3.9
481 if (isSubImage)
482 {
483 switch (formatInfo.format)
484 {
485 case GL_ALPHA:
486 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400487 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
488 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500490 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400491 return false;
492 }
493 break;
494 case GL_LUMINANCE:
495 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
496 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
497 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400498 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
499 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500501 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400502 return false;
503 }
504 break;
505 case GL_RED_EXT:
506 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
507 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
508 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
509 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
510 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400511 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
512 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500514 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400515 return false;
516 }
517 break;
518 case GL_RG_EXT:
519 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
520 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
521 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
522 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400523 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
524 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500526 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400527 return false;
528 }
529 break;
530 case GL_RGB:
531 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
532 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
533 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400534 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
535 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500537 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400538 return false;
539 }
540 break;
541 case GL_LUMINANCE_ALPHA:
542 case GL_RGBA:
543 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400544 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
545 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500547 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400548 return false;
549 }
550 break;
551 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
552 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
553 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
554 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
555 case GL_ETC1_RGB8_OES:
556 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
557 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
558 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
559 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
560 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500561 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 return false;
563 case GL_DEPTH_COMPONENT:
564 case GL_DEPTH_STENCIL_OES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500565 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400566 return false;
567 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500568 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400569 return false;
570 }
571
572 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500574 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400575 return false;
576 }
577 }
578 else
579 {
580 switch (internalformat)
581 {
582 case GL_ALPHA:
583 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
584 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
585 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500587 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400588 return false;
589 }
590 break;
591 case GL_LUMINANCE:
592 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
593 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
594 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
595 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
596 colorbufferFormat != GL_BGR5_A1_ANGLEX)
597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500598 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400599 return false;
600 }
601 break;
602 case GL_RED_EXT:
603 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
604 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
605 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
606 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
607 colorbufferFormat != GL_BGR5_A1_ANGLEX)
608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500609 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400610 return false;
611 }
612 break;
613 case GL_RG_EXT:
614 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
615 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
616 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
617 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500619 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400620 return false;
621 }
622 break;
623 case GL_RGB:
624 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
625 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
626 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
627 colorbufferFormat != GL_BGR5_A1_ANGLEX)
628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500629 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400630 return false;
631 }
632 break;
633 case GL_LUMINANCE_ALPHA:
634 case GL_RGBA:
635 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
636 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
637 colorbufferFormat != GL_BGR5_A1_ANGLEX)
638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500639 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400640 return false;
641 }
642 break;
643 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
644 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
645 if (context->getExtensions().textureCompressionDXT1)
646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500647 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400648 return false;
649 }
650 else
651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500652 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400653 return false;
654 }
655 break;
656 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
657 if (context->getExtensions().textureCompressionDXT3)
658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500659 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400660 return false;
661 }
662 else
663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500664 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666 }
667 break;
668 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
669 if (context->getExtensions().textureCompressionDXT5)
670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500671 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400672 return false;
673 }
674 else
675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500676 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400677 return false;
678 }
679 break;
680 case GL_ETC1_RGB8_OES:
681 if (context->getExtensions().compressedETC1RGB8Texture)
682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500683 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400684 return false;
685 }
686 else
687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500688 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 return false;
690 }
691 break;
692 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
693 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
694 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
695 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
696 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
697 if (context->getExtensions().lossyETCDecode)
698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 context->handleError(InvalidOperation()
700 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400701 return false;
702 }
703 else
704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500705 context->handleError(InvalidEnum()
706 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400707 return false;
708 }
709 break;
710 case GL_DEPTH_COMPONENT:
711 case GL_DEPTH_COMPONENT16:
712 case GL_DEPTH_COMPONENT32_OES:
713 case GL_DEPTH_STENCIL_OES:
714 case GL_DEPTH24_STENCIL8_OES:
715 if (context->getExtensions().depthTextures)
716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500717 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400718 return false;
719 }
720 else
721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500722 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400727 return false;
728 }
729 }
730
731 // If width or height is zero, it is a no-op. Return false without setting an error.
732 return (width > 0 && height > 0);
733}
734
735bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
736{
737 switch (cap)
738 {
739 // EXT_multisample_compatibility
740 case GL_MULTISAMPLE_EXT:
741 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
742 return context->getExtensions().multisampleCompatibility;
743
744 case GL_CULL_FACE:
745 case GL_POLYGON_OFFSET_FILL:
746 case GL_SAMPLE_ALPHA_TO_COVERAGE:
747 case GL_SAMPLE_COVERAGE:
748 case GL_SCISSOR_TEST:
749 case GL_STENCIL_TEST:
750 case GL_DEPTH_TEST:
751 case GL_BLEND:
752 case GL_DITHER:
753 return true;
754
755 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
756 case GL_RASTERIZER_DISCARD:
757 return (context->getClientMajorVersion() >= 3);
758
759 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
760 case GL_DEBUG_OUTPUT:
761 return context->getExtensions().debug;
762
763 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
764 return queryOnly && context->getExtensions().bindGeneratesResource;
765
766 case GL_CLIENT_ARRAYS_ANGLE:
767 return queryOnly && context->getExtensions().clientArrays;
768
769 case GL_FRAMEBUFFER_SRGB_EXT:
770 return context->getExtensions().sRGBWriteControl;
771
772 case GL_SAMPLE_MASK:
773 return context->getClientVersion() >= Version(3, 1);
774
775 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
776 return queryOnly && context->getExtensions().robustResourceInitialization;
777
778 default:
779 return false;
780 }
781}
782
Geoff Langfc32e8b2017-05-31 14:16:59 -0400783// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
784// 3.1.
785bool IsValidESSLCharacter(unsigned char c)
786{
787 // Printing characters are valid except " $ ` @ \ ' DEL.
788 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
789 c != '\'')
790 {
791 return true;
792 }
793
794 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
795 if (c >= 9 && c <= 13)
796 {
797 return true;
798 }
799
800 return false;
801}
802
803bool IsValidESSLString(const char *str, size_t len)
804{
805 return len == 0 || std::find_if_not(str, str + len, IsValidESSLCharacter) == str + len;
806}
807
Jamie Madillc29968b2016-01-20 11:17:23 -0500808} // anonymous namespace
809
Geoff Langff5b2d52016-09-07 11:32:23 -0400810bool ValidateES2TexImageParameters(Context *context,
811 GLenum target,
812 GLint level,
813 GLenum internalformat,
814 bool isCompressed,
815 bool isSubImage,
816 GLint xoffset,
817 GLint yoffset,
818 GLsizei width,
819 GLsizei height,
820 GLint border,
821 GLenum format,
822 GLenum type,
823 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400824 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825{
Jamie Madill6f38f822014-06-06 17:12:20 -0400826 if (!ValidTexture2DDestinationTarget(context, target))
827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500828 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400830 }
831
Austin Kinross08528e12015-10-07 16:24:40 -0700832 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500834 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 }
837
He Yunchaoced53ae2016-11-29 15:00:51 +0800838 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 std::numeric_limits<GLsizei>::max() - yoffset < height)
840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500841 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 }
844
Geoff Lang6e898aa2017-06-02 11:17:26 -0400845 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
846 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
847 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
848 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
849 // case.
850 bool nonEqualFormatsAllowed =
851 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
852 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
853
854 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500856 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400857 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 }
859
Geoff Langaae65a42014-05-26 12:43:44 -0400860 const gl::Caps &caps = context->getCaps();
861
Geoff Langa9be0dc2014-12-17 12:34:40 -0500862 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500864 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
865 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500867 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500868 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500870 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500871 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500872 {
873 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500875 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500876 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878
Geoff Langa9be0dc2014-12-17 12:34:40 -0500879 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
880 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500882 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500883 return false;
884 }
885 }
886 else
887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500888 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400889 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400890 }
891
He Yunchaoced53ae2016-11-29 15:00:51 +0800892 gl::Texture *texture =
893 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894 if (!texture)
895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500896 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400897 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400898 }
899
Geoff Langa9be0dc2014-12-17 12:34:40 -0500900 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901 {
Geoff Langca271392017-04-05 12:30:00 -0400902 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
903 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500905 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500906 return false;
907 }
908
Geoff Langa9be0dc2014-12-17 12:34:40 -0500909 if (format != GL_NONE)
910 {
Geoff Langca271392017-04-05 12:30:00 -0400911 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
912 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500914 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500915 return false;
916 }
917 }
918
919 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
920 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500922 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500923 return false;
924 }
925 }
926 else
927 {
Geoff Lang69cce582015-09-17 13:20:36 -0400928 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500930 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500931 return false;
932 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400933 }
934
935 // Verify zero border
936 if (border != 0)
937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500938 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400939 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 }
941
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 if (isCompressed)
943 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400944 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400945 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
946 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 switch (actualInternalFormat)
948 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800949 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
950 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
951 if (!context->getExtensions().textureCompressionDXT1)
952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500953 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800954 return false;
955 }
956 break;
957 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
958 if (!context->getExtensions().textureCompressionDXT1)
959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500960 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800961 return false;
962 }
963 break;
964 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
965 if (!context->getExtensions().textureCompressionDXT5)
966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500967 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800968 return false;
969 }
970 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800971 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
972 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
973 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
974 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
975 if (!context->getExtensions().textureCompressionS3TCsRGB)
976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500977 context->handleError(InvalidEnum());
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800978 return false;
979 }
980 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 case GL_ETC1_RGB8_OES:
982 if (!context->getExtensions().compressedETC1RGB8Texture)
983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500984 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 return false;
986 }
987 break;
988 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800989 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
990 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
991 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
992 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800993 if (!context->getExtensions().lossyETCDecode)
994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500995 context->handleError(InvalidEnum()
996 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 return false;
998 }
999 break;
1000 default:
1001 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001002 InvalidEnum()
1003 << "internalformat is not a supported compressed internal format");
Geoff Langb1196682014-07-23 13:47:29 -04001004 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001005 }
Geoff Lang966c9402017-04-18 12:38:27 -04001006
1007 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001008 {
Geoff Lang966c9402017-04-18 12:38:27 -04001009 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1010 height, texture->getWidth(target, level),
1011 texture->getHeight(target, level)))
1012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001014 return false;
1015 }
1016
1017 if (format != actualInternalFormat)
1018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidOperation()
1020 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -04001021 return false;
1022 }
1023 }
1024 else
1025 {
1026 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001028 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001029 return false;
1030 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 }
1032 }
1033 else
1034 {
1035 // validate <type> by itself (used as secondary key below)
1036 switch (type)
1037 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001038 case GL_UNSIGNED_BYTE:
1039 case GL_UNSIGNED_SHORT_5_6_5:
1040 case GL_UNSIGNED_SHORT_4_4_4_4:
1041 case GL_UNSIGNED_SHORT_5_5_5_1:
1042 case GL_UNSIGNED_SHORT:
1043 case GL_UNSIGNED_INT:
1044 case GL_UNSIGNED_INT_24_8_OES:
1045 case GL_HALF_FLOAT_OES:
1046 case GL_FLOAT:
1047 break;
1048 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001049 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052
1053 // validate <format> + <type> combinations
1054 // - invalid <format> -> sets INVALID_ENUM
1055 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1056 switch (format)
1057 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 case GL_ALPHA:
1059 case GL_LUMINANCE:
1060 case GL_LUMINANCE_ALPHA:
1061 switch (type)
1062 {
1063 case GL_UNSIGNED_BYTE:
1064 case GL_FLOAT:
1065 case GL_HALF_FLOAT_OES:
1066 break;
1067 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001068 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001069 return false;
1070 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_RED:
1073 case GL_RG:
1074 if (!context->getExtensions().textureRG)
1075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001076 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 return false;
1078 }
1079 switch (type)
1080 {
1081 case GL_UNSIGNED_BYTE:
1082 case GL_FLOAT:
1083 case GL_HALF_FLOAT_OES:
1084 break;
1085 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001086 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001087 return false;
1088 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001090 case GL_RGB:
1091 switch (type)
1092 {
1093 case GL_UNSIGNED_BYTE:
1094 case GL_UNSIGNED_SHORT_5_6_5:
1095 case GL_FLOAT:
1096 case GL_HALF_FLOAT_OES:
1097 break;
1098 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001099 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001100 return false;
1101 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001102 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 case GL_RGBA:
1104 switch (type)
1105 {
1106 case GL_UNSIGNED_BYTE:
1107 case GL_UNSIGNED_SHORT_4_4_4_4:
1108 case GL_UNSIGNED_SHORT_5_5_5_1:
1109 case GL_FLOAT:
1110 case GL_HALF_FLOAT_OES:
1111 break;
1112 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001113 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 return false;
1115 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 case GL_BGRA_EXT:
1118 switch (type)
1119 {
1120 case GL_UNSIGNED_BYTE:
1121 break;
1122 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001123 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 return false;
1125 }
1126 break;
1127 case GL_SRGB_EXT:
1128 case GL_SRGB_ALPHA_EXT:
1129 if (!context->getExtensions().sRGB)
1130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001131 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001132 return false;
1133 }
1134 switch (type)
1135 {
1136 case GL_UNSIGNED_BYTE:
1137 break;
1138 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001139 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 return false;
1141 }
1142 break;
1143 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1144 // handled below
1145 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1146 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1147 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1148 break;
1149 case GL_DEPTH_COMPONENT:
1150 switch (type)
1151 {
1152 case GL_UNSIGNED_SHORT:
1153 case GL_UNSIGNED_INT:
1154 break;
1155 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001157 return false;
1158 }
1159 break;
1160 case GL_DEPTH_STENCIL_OES:
1161 switch (type)
1162 {
1163 case GL_UNSIGNED_INT_24_8_OES:
1164 break;
1165 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001166 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001167 return false;
1168 }
1169 break;
1170 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
1175 switch (format)
1176 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1178 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1179 if (context->getExtensions().textureCompressionDXT1)
1180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001181 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001182 return false;
1183 }
1184 else
1185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001186 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001187 return false;
1188 }
1189 break;
1190 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1191 if (context->getExtensions().textureCompressionDXT3)
1192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 return false;
1195 }
1196 else
1197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001198 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001199 return false;
1200 }
1201 break;
1202 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1203 if (context->getExtensions().textureCompressionDXT5)
1204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001205 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return false;
1207 }
1208 else
1209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001210 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001211 return false;
1212 }
1213 break;
1214 case GL_ETC1_RGB8_OES:
1215 if (context->getExtensions().compressedETC1RGB8Texture)
1216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001217 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 return false;
1219 }
1220 else
1221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001222 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001223 return false;
1224 }
1225 break;
1226 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001227 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1228 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1229 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1230 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001231 if (context->getExtensions().lossyETCDecode)
1232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidOperation()
1234 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001235 return false;
1236 }
1237 else
1238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001239 context->handleError(InvalidEnum()
1240 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001241 return false;
1242 }
1243 break;
1244 case GL_DEPTH_COMPONENT:
1245 case GL_DEPTH_STENCIL_OES:
1246 if (!context->getExtensions().depthTextures)
1247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001249 return false;
1250 }
1251 if (target != GL_TEXTURE_2D)
1252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001253 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001254 return false;
1255 }
1256 // OES_depth_texture supports loading depth data and multiple levels,
1257 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001258 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001261 return false;
1262 }
1263 break;
1264 default:
1265 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001266 }
1267
Geoff Lang6e898aa2017-06-02 11:17:26 -04001268 if (!isSubImage)
1269 {
1270 switch (internalformat)
1271 {
1272 case GL_RGBA32F:
1273 if (!context->getExtensions().colorBufferFloatRGBA)
1274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001275 context->handleError(InvalidValue()
1276 << "Sized GL_RGBA32F internal format requires "
1277 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001278 return false;
1279 }
1280 if (type != GL_FLOAT)
1281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001282 context->handleError(InvalidOperation()
1283 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001284 return false;
1285 }
1286 if (format != GL_RGBA)
1287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001288 context->handleError(InvalidOperation()
1289 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001290 return false;
1291 }
1292 break;
1293
1294 case GL_RGB32F:
1295 if (!context->getExtensions().colorBufferFloatRGB)
1296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001297 context->handleError(InvalidValue()
1298 << "Sized GL_RGB32F internal format requires "
1299 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001300 return false;
1301 }
1302 if (type != GL_FLOAT)
1303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001304 context->handleError(InvalidOperation()
1305 << "Invalid internal format/type combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001306 return false;
1307 }
1308 if (format != GL_RGB)
1309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001310 context->handleError(InvalidOperation()
1311 << "Invalid internal format/format combination");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001312 return false;
1313 }
1314 break;
1315
1316 default:
1317 break;
1318 }
1319 }
1320
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 if (type == GL_FLOAT)
1322 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001323 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 }
1328 }
1329 else if (type == GL_HALF_FLOAT_OES)
1330 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001331 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001333 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 }
1336 }
1337 }
1338
Geoff Langff5b2d52016-09-07 11:32:23 -04001339 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
1340 imageSize))
1341 {
1342 return false;
1343 }
1344
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001345 return true;
1346}
1347
He Yunchaoced53ae2016-11-29 15:00:51 +08001348bool ValidateES2TexStorageParameters(Context *context,
1349 GLenum target,
1350 GLsizei levels,
1351 GLenum internalformat,
1352 GLsizei width,
1353 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354{
1355 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 }
1360
1361 if (width < 1 || height < 1 || levels < 1)
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
1366
1367 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
1372
1373 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001375 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001376 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 }
1378
Geoff Langca271392017-04-05 12:30:00 -04001379 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001380 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001382 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 }
1385
Geoff Langaae65a42014-05-26 12:43:44 -04001386 const gl::Caps &caps = context->getCaps();
1387
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 switch (target)
1389 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001390 case GL_TEXTURE_2D:
1391 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1392 static_cast<GLuint>(height) > caps.max2DTextureSize)
1393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001395 return false;
1396 }
1397 break;
1398 case GL_TEXTURE_CUBE_MAP:
1399 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1400 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001403 return false;
1404 }
1405 break;
1406 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001408 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 }
1410
Geoff Langc0b9ef42014-07-02 10:02:37 -04001411 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 {
1413 if (!gl::isPow2(width) || !gl::isPow2(height))
1414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001416 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
1418 }
1419
1420 switch (internalformat)
1421 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001422 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1423 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1424 if (!context->getExtensions().textureCompressionDXT1)
1425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001426 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001427 return false;
1428 }
1429 break;
1430 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1431 if (!context->getExtensions().textureCompressionDXT3)
1432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001434 return false;
1435 }
1436 break;
1437 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1438 if (!context->getExtensions().textureCompressionDXT5)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001441 return false;
1442 }
1443 break;
1444 case GL_ETC1_RGB8_OES:
1445 if (!context->getExtensions().compressedETC1RGB8Texture)
1446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001447 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001448 return false;
1449 }
1450 break;
1451 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001452 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1453 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1454 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1455 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001456 if (!context->getExtensions().lossyETCDecode)
1457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001458 context->handleError(InvalidEnum()
1459 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 return false;
1461 }
1462 break;
1463 case GL_RGBA32F_EXT:
1464 case GL_RGB32F_EXT:
1465 case GL_ALPHA32F_EXT:
1466 case GL_LUMINANCE32F_EXT:
1467 case GL_LUMINANCE_ALPHA32F_EXT:
1468 if (!context->getExtensions().textureFloat)
1469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001470 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001471 return false;
1472 }
1473 break;
1474 case GL_RGBA16F_EXT:
1475 case GL_RGB16F_EXT:
1476 case GL_ALPHA16F_EXT:
1477 case GL_LUMINANCE16F_EXT:
1478 case GL_LUMINANCE_ALPHA16F_EXT:
1479 if (!context->getExtensions().textureHalfFloat)
1480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001481 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001482 return false;
1483 }
1484 break;
1485 case GL_R8_EXT:
1486 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001487 if (!context->getExtensions().textureRG)
1488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001490 return false;
1491 }
1492 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001493 case GL_R16F_EXT:
1494 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001495 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001498 return false;
1499 }
1500 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001501 case GL_R32F_EXT:
1502 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001503 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001505 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001506 return false;
1507 }
1508 break;
1509 case GL_DEPTH_COMPONENT16:
1510 case GL_DEPTH_COMPONENT32_OES:
1511 case GL_DEPTH24_STENCIL8_OES:
1512 if (!context->getExtensions().depthTextures)
1513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001514 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001515 return false;
1516 }
1517 if (target != GL_TEXTURE_2D)
1518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001519 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001520 return false;
1521 }
1522 // ANGLE_depth_texture only supports 1-level textures
1523 if (levels != 1)
1524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001525 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001526 return false;
1527 }
1528 break;
1529 default:
1530 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Geoff Lang691e58c2014-12-19 17:03:25 -05001533 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 if (!texture || texture->id() == 0)
1535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001536 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
1539
Geoff Lang69cce582015-09-17 13:20:36 -04001540 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001542 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001543 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001544 }
1545
1546 return true;
1547}
1548
He Yunchaoced53ae2016-11-29 15:00:51 +08001549bool ValidateDiscardFramebufferEXT(Context *context,
1550 GLenum target,
1551 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001552 const GLenum *attachments)
1553{
Jamie Madillc29968b2016-01-20 11:17:23 -05001554 if (!context->getExtensions().discardFramebuffer)
1555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001556 context->handleError(InvalidOperation() << "Extension not enabled");
Jamie Madillc29968b2016-01-20 11:17:23 -05001557 return false;
1558 }
1559
Austin Kinross08332632015-05-05 13:35:47 -07001560 bool defaultFramebuffer = false;
1561
1562 switch (target)
1563 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001564 case GL_FRAMEBUFFER:
1565 defaultFramebuffer =
1566 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1567 break;
1568 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001569 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001570 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001571 }
1572
He Yunchaoced53ae2016-11-29 15:00:51 +08001573 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1574 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001575}
1576
Austin Kinrossbc781f32015-10-26 09:27:38 -07001577bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1578{
1579 if (!context->getExtensions().vertexArrayObject)
1580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001581 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001582 return false;
1583 }
1584
1585 return ValidateBindVertexArrayBase(context, array);
1586}
1587
1588bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1589{
1590 if (!context->getExtensions().vertexArrayObject)
1591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001592 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001593 return false;
1594 }
1595
Olli Etuaho41997e72016-03-10 13:38:39 +02001596 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001597}
1598
1599bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1600{
1601 if (!context->getExtensions().vertexArrayObject)
1602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001603 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001604 return false;
1605 }
1606
Olli Etuaho41997e72016-03-10 13:38:39 +02001607 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001608}
1609
1610bool ValidateIsVertexArrayOES(Context *context)
1611{
1612 if (!context->getExtensions().vertexArrayObject)
1613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001614 context->handleError(InvalidOperation() << "Extension not enabled");
Austin Kinrossbc781f32015-10-26 09:27:38 -07001615 return false;
1616 }
1617
1618 return true;
1619}
Geoff Langc5629752015-12-07 16:29:04 -05001620
1621bool ValidateProgramBinaryOES(Context *context,
1622 GLuint program,
1623 GLenum binaryFormat,
1624 const void *binary,
1625 GLint length)
1626{
1627 if (!context->getExtensions().getProgramBinary)
1628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001629 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001630 return false;
1631 }
1632
1633 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1634}
1635
1636bool ValidateGetProgramBinaryOES(Context *context,
1637 GLuint program,
1638 GLsizei bufSize,
1639 GLsizei *length,
1640 GLenum *binaryFormat,
1641 void *binary)
1642{
1643 if (!context->getExtensions().getProgramBinary)
1644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Langc5629752015-12-07 16:29:04 -05001646 return false;
1647 }
1648
1649 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1650}
Geoff Lange102fee2015-12-10 11:23:30 -05001651
Geoff Lang70d0f492015-12-10 17:45:46 -05001652static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1653{
1654 switch (source)
1655 {
1656 case GL_DEBUG_SOURCE_API:
1657 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1658 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1659 case GL_DEBUG_SOURCE_OTHER:
1660 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1661 return !mustBeThirdPartyOrApplication;
1662
1663 case GL_DEBUG_SOURCE_THIRD_PARTY:
1664 case GL_DEBUG_SOURCE_APPLICATION:
1665 return true;
1666
1667 default:
1668 return false;
1669 }
1670}
1671
1672static bool ValidDebugType(GLenum type)
1673{
1674 switch (type)
1675 {
1676 case GL_DEBUG_TYPE_ERROR:
1677 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1678 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1679 case GL_DEBUG_TYPE_PERFORMANCE:
1680 case GL_DEBUG_TYPE_PORTABILITY:
1681 case GL_DEBUG_TYPE_OTHER:
1682 case GL_DEBUG_TYPE_MARKER:
1683 case GL_DEBUG_TYPE_PUSH_GROUP:
1684 case GL_DEBUG_TYPE_POP_GROUP:
1685 return true;
1686
1687 default:
1688 return false;
1689 }
1690}
1691
1692static bool ValidDebugSeverity(GLenum severity)
1693{
1694 switch (severity)
1695 {
1696 case GL_DEBUG_SEVERITY_HIGH:
1697 case GL_DEBUG_SEVERITY_MEDIUM:
1698 case GL_DEBUG_SEVERITY_LOW:
1699 case GL_DEBUG_SEVERITY_NOTIFICATION:
1700 return true;
1701
1702 default:
1703 return false;
1704 }
1705}
1706
Geoff Lange102fee2015-12-10 11:23:30 -05001707bool ValidateDebugMessageControlKHR(Context *context,
1708 GLenum source,
1709 GLenum type,
1710 GLenum severity,
1711 GLsizei count,
1712 const GLuint *ids,
1713 GLboolean enabled)
1714{
1715 if (!context->getExtensions().debug)
1716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001717 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001718 return false;
1719 }
1720
Geoff Lang70d0f492015-12-10 17:45:46 -05001721 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001724 return false;
1725 }
1726
1727 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001730 return false;
1731 }
1732
1733 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001735 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001736 return false;
1737 }
1738
1739 if (count > 0)
1740 {
1741 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(
1744 InvalidOperation()
1745 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001746 return false;
1747 }
1748
1749 if (severity != GL_DONT_CARE)
1750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001752 InvalidOperation()
1753 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001754 return false;
1755 }
1756 }
1757
Geoff Lange102fee2015-12-10 11:23:30 -05001758 return true;
1759}
1760
1761bool ValidateDebugMessageInsertKHR(Context *context,
1762 GLenum source,
1763 GLenum type,
1764 GLuint id,
1765 GLenum severity,
1766 GLsizei length,
1767 const GLchar *buf)
1768{
1769 if (!context->getExtensions().debug)
1770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001771 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001772 return false;
1773 }
1774
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001775 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001776 {
1777 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1778 // not generate an error.
1779 return false;
1780 }
1781
1782 if (!ValidDebugSeverity(severity))
1783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001784 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001785 return false;
1786 }
1787
1788 if (!ValidDebugType(type))
1789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001790 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001791 return false;
1792 }
1793
1794 if (!ValidDebugSource(source, true))
1795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001796 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001797 return false;
1798 }
1799
1800 size_t messageLength = (length < 0) ? strlen(buf) : length;
1801 if (messageLength > context->getExtensions().maxDebugMessageLength)
1802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001803 context->handleError(InvalidValue()
1804 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001805 return false;
1806 }
1807
Geoff Lange102fee2015-12-10 11:23:30 -05001808 return true;
1809}
1810
1811bool ValidateDebugMessageCallbackKHR(Context *context,
1812 GLDEBUGPROCKHR callback,
1813 const void *userParam)
1814{
1815 if (!context->getExtensions().debug)
1816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001817 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001818 return false;
1819 }
1820
Geoff Lange102fee2015-12-10 11:23:30 -05001821 return true;
1822}
1823
1824bool ValidateGetDebugMessageLogKHR(Context *context,
1825 GLuint count,
1826 GLsizei bufSize,
1827 GLenum *sources,
1828 GLenum *types,
1829 GLuint *ids,
1830 GLenum *severities,
1831 GLsizei *lengths,
1832 GLchar *messageLog)
1833{
1834 if (!context->getExtensions().debug)
1835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001836 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001837 return false;
1838 }
1839
Geoff Lang70d0f492015-12-10 17:45:46 -05001840 if (bufSize < 0 && messageLog != nullptr)
1841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001842 context->handleError(InvalidValue()
1843 << "bufSize must be positive if messageLog is not null.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001844 return false;
1845 }
1846
Geoff Lange102fee2015-12-10 11:23:30 -05001847 return true;
1848}
1849
1850bool ValidatePushDebugGroupKHR(Context *context,
1851 GLenum source,
1852 GLuint id,
1853 GLsizei length,
1854 const GLchar *message)
1855{
1856 if (!context->getExtensions().debug)
1857 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001858 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001859 return false;
1860 }
1861
Geoff Lang70d0f492015-12-10 17:45:46 -05001862 if (!ValidDebugSource(source, true))
1863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001864 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001865 return false;
1866 }
1867
1868 size_t messageLength = (length < 0) ? strlen(message) : length;
1869 if (messageLength > context->getExtensions().maxDebugMessageLength)
1870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001871 context->handleError(InvalidValue()
1872 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001873 return false;
1874 }
1875
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001876 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001877 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001879 context
1880 ->handleError(StackOverflow()
1881 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001882 return false;
1883 }
1884
Geoff Lange102fee2015-12-10 11:23:30 -05001885 return true;
1886}
1887
1888bool ValidatePopDebugGroupKHR(Context *context)
1889{
1890 if (!context->getExtensions().debug)
1891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001892 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05001893 return false;
1894 }
1895
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001896 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001897 if (currentStackSize <= 1)
1898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001899 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001900 return false;
1901 }
1902
1903 return true;
1904}
1905
1906static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1907{
1908 switch (identifier)
1909 {
1910 case GL_BUFFER:
1911 if (context->getBuffer(name) == nullptr)
1912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001913 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001914 return false;
1915 }
1916 return true;
1917
1918 case GL_SHADER:
1919 if (context->getShader(name) == nullptr)
1920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001921 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001922 return false;
1923 }
1924 return true;
1925
1926 case GL_PROGRAM:
1927 if (context->getProgram(name) == nullptr)
1928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001929 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001930 return false;
1931 }
1932 return true;
1933
1934 case GL_VERTEX_ARRAY:
1935 if (context->getVertexArray(name) == nullptr)
1936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001937 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001938 return false;
1939 }
1940 return true;
1941
1942 case GL_QUERY:
1943 if (context->getQuery(name) == nullptr)
1944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001945 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001946 return false;
1947 }
1948 return true;
1949
1950 case GL_TRANSFORM_FEEDBACK:
1951 if (context->getTransformFeedback(name) == nullptr)
1952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001953 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001954 return false;
1955 }
1956 return true;
1957
1958 case GL_SAMPLER:
1959 if (context->getSampler(name) == nullptr)
1960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001961 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001962 return false;
1963 }
1964 return true;
1965
1966 case GL_TEXTURE:
1967 if (context->getTexture(name) == nullptr)
1968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001969 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001970 return false;
1971 }
1972 return true;
1973
1974 case GL_RENDERBUFFER:
1975 if (context->getRenderbuffer(name) == nullptr)
1976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001977 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001978 return false;
1979 }
1980 return true;
1981
1982 case GL_FRAMEBUFFER:
1983 if (context->getFramebuffer(name) == nullptr)
1984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001985 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001986 return false;
1987 }
1988 return true;
1989
1990 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001991 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001992 return false;
1993 }
Geoff Lange102fee2015-12-10 11:23:30 -05001994}
1995
Martin Radev9d901792016-07-15 15:58:58 +03001996static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1997{
1998 size_t labelLength = 0;
1999
2000 if (length < 0)
2001 {
2002 if (label != nullptr)
2003 {
2004 labelLength = strlen(label);
2005 }
2006 }
2007 else
2008 {
2009 labelLength = static_cast<size_t>(length);
2010 }
2011
2012 if (labelLength > context->getExtensions().maxLabelLength)
2013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002014 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002015 return false;
2016 }
2017
2018 return true;
2019}
2020
Geoff Lange102fee2015-12-10 11:23:30 -05002021bool ValidateObjectLabelKHR(Context *context,
2022 GLenum identifier,
2023 GLuint name,
2024 GLsizei length,
2025 const GLchar *label)
2026{
2027 if (!context->getExtensions().debug)
2028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002029 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002030 return false;
2031 }
2032
Geoff Lang70d0f492015-12-10 17:45:46 -05002033 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2034 {
2035 return false;
2036 }
2037
Martin Radev9d901792016-07-15 15:58:58 +03002038 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002039 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002040 return false;
2041 }
2042
Geoff Lange102fee2015-12-10 11:23:30 -05002043 return true;
2044}
2045
2046bool ValidateGetObjectLabelKHR(Context *context,
2047 GLenum identifier,
2048 GLuint name,
2049 GLsizei bufSize,
2050 GLsizei *length,
2051 GLchar *label)
2052{
2053 if (!context->getExtensions().debug)
2054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002055 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002056 return false;
2057 }
2058
Geoff Lang70d0f492015-12-10 17:45:46 -05002059 if (bufSize < 0)
2060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002061 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002062 return false;
2063 }
2064
2065 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2066 {
2067 return false;
2068 }
2069
Martin Radev9d901792016-07-15 15:58:58 +03002070 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002071}
2072
2073static bool ValidateObjectPtrName(Context *context, const void *ptr)
2074{
2075 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002077 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002078 return false;
2079 }
2080
Geoff Lange102fee2015-12-10 11:23:30 -05002081 return true;
2082}
2083
2084bool ValidateObjectPtrLabelKHR(Context *context,
2085 const void *ptr,
2086 GLsizei length,
2087 const GLchar *label)
2088{
2089 if (!context->getExtensions().debug)
2090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002091 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002092 return false;
2093 }
2094
Geoff Lang70d0f492015-12-10 17:45:46 -05002095 if (!ValidateObjectPtrName(context, ptr))
2096 {
2097 return false;
2098 }
2099
Martin Radev9d901792016-07-15 15:58:58 +03002100 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002101 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002102 return false;
2103 }
2104
Geoff Lange102fee2015-12-10 11:23:30 -05002105 return true;
2106}
2107
2108bool ValidateGetObjectPtrLabelKHR(Context *context,
2109 const void *ptr,
2110 GLsizei bufSize,
2111 GLsizei *length,
2112 GLchar *label)
2113{
2114 if (!context->getExtensions().debug)
2115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002116 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002117 return false;
2118 }
2119
Geoff Lang70d0f492015-12-10 17:45:46 -05002120 if (bufSize < 0)
2121 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002122 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002123 return false;
2124 }
2125
2126 if (!ValidateObjectPtrName(context, ptr))
2127 {
2128 return false;
2129 }
2130
Martin Radev9d901792016-07-15 15:58:58 +03002131 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002132}
2133
2134bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2135{
2136 if (!context->getExtensions().debug)
2137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002138 context->handleError(InvalidOperation() << "Extension not enabled");
Geoff Lange102fee2015-12-10 11:23:30 -05002139 return false;
2140 }
2141
Geoff Lang70d0f492015-12-10 17:45:46 -05002142 // TODO: represent this in Context::getQueryParameterInfo.
2143 switch (pname)
2144 {
2145 case GL_DEBUG_CALLBACK_FUNCTION:
2146 case GL_DEBUG_CALLBACK_USER_PARAM:
2147 break;
2148
2149 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002150 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002151 return false;
2152 }
2153
Geoff Lange102fee2015-12-10 11:23:30 -05002154 return true;
2155}
Jamie Madillc29968b2016-01-20 11:17:23 -05002156
2157bool ValidateBlitFramebufferANGLE(Context *context,
2158 GLint srcX0,
2159 GLint srcY0,
2160 GLint srcX1,
2161 GLint srcY1,
2162 GLint dstX0,
2163 GLint dstY0,
2164 GLint dstX1,
2165 GLint dstY1,
2166 GLbitfield mask,
2167 GLenum filter)
2168{
2169 if (!context->getExtensions().framebufferBlit)
2170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002171 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002172 return false;
2173 }
2174
2175 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2176 {
2177 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002178 context->handleError(InvalidOperation() << "Scaling and flipping in "
2179 "BlitFramebufferANGLE not supported by this "
2180 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002181 return false;
2182 }
2183
2184 if (filter == GL_LINEAR)
2185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002186 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002187 return false;
2188 }
2189
Jamie Madill51f40ec2016-06-15 14:06:00 -04002190 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2191 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002192
2193 if (mask & GL_COLOR_BUFFER_BIT)
2194 {
2195 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2196 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2197
2198 if (readColorAttachment && drawColorAttachment)
2199 {
2200 if (!(readColorAttachment->type() == GL_TEXTURE &&
2201 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2202 readColorAttachment->type() != GL_RENDERBUFFER &&
2203 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002205 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002206 return false;
2207 }
2208
Geoff Langa15472a2015-08-11 11:48:03 -04002209 for (size_t drawbufferIdx = 0;
2210 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002211 {
Geoff Langa15472a2015-08-11 11:48:03 -04002212 const FramebufferAttachment *attachment =
2213 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2214 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002215 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002216 if (!(attachment->type() == GL_TEXTURE &&
2217 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2218 attachment->type() != GL_RENDERBUFFER &&
2219 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002221 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002222 return false;
2223 }
2224
2225 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002226 if (!Format::SameSized(attachment->getFormat(),
2227 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002229 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002230 return false;
2231 }
2232 }
2233 }
2234
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002235 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002236 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2237 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002239 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002240 return false;
2241 }
2242 }
2243 }
2244
2245 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2246 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2247 for (size_t i = 0; i < 2; i++)
2248 {
2249 if (mask & masks[i])
2250 {
2251 const FramebufferAttachment *readBuffer =
2252 readFramebuffer->getAttachment(attachments[i]);
2253 const FramebufferAttachment *drawBuffer =
2254 drawFramebuffer->getAttachment(attachments[i]);
2255
2256 if (readBuffer && drawBuffer)
2257 {
2258 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2259 dstX0, dstY0, dstX1, dstY1))
2260 {
2261 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002262 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2263 "stencil blits are supported by "
2264 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002265 return false;
2266 }
2267
2268 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002270 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002271 return false;
2272 }
2273 }
2274 }
2275 }
2276
2277 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2278 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002279}
Jamie Madillc29968b2016-01-20 11:17:23 -05002280
2281bool ValidateClear(ValidationContext *context, GLbitfield mask)
2282{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002283 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002284 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002286 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002287 return false;
2288 }
2289
2290 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002292 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05002293 return false;
2294 }
2295
Geoff Lang76e65652017-03-27 14:58:02 -04002296 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2297 {
2298 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2299 GL_SIGNED_NORMALIZED};
2300
2301 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2302 drawBufferIdx++)
2303 {
2304 if (!ValidateWebGLFramebufferAttachmentClearType(
2305 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2306 {
2307 return false;
2308 }
2309 }
2310 }
2311
Jamie Madillc29968b2016-01-20 11:17:23 -05002312 return true;
2313}
2314
2315bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2316{
2317 if (!context->getExtensions().drawBuffers)
2318 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002319 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002320 return false;
2321 }
2322
2323 return ValidateDrawBuffersBase(context, n, bufs);
2324}
2325
Jamie Madill73a84962016-02-12 09:27:23 -05002326bool ValidateTexImage2D(Context *context,
2327 GLenum target,
2328 GLint level,
2329 GLint internalformat,
2330 GLsizei width,
2331 GLsizei height,
2332 GLint border,
2333 GLenum format,
2334 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002335 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002336{
Martin Radev1be913c2016-07-11 17:59:16 +03002337 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002338 {
2339 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002340 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002341 }
2342
Martin Radev1be913c2016-07-11 17:59:16 +03002343 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002344 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002345 0, 0, width, height, 1, border, format, type, -1,
2346 pixels);
2347}
2348
2349bool ValidateTexImage2DRobust(Context *context,
2350 GLenum target,
2351 GLint level,
2352 GLint internalformat,
2353 GLsizei width,
2354 GLsizei height,
2355 GLint border,
2356 GLenum format,
2357 GLenum type,
2358 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002359 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002360{
2361 if (!ValidateRobustEntryPoint(context, bufSize))
2362 {
2363 return false;
2364 }
2365
2366 if (context->getClientMajorVersion() < 3)
2367 {
2368 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2369 0, 0, width, height, border, format, type, bufSize,
2370 pixels);
2371 }
2372
2373 ASSERT(context->getClientMajorVersion() >= 3);
2374 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2375 0, 0, width, height, 1, border, format, type, bufSize,
2376 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002377}
2378
2379bool ValidateTexSubImage2D(Context *context,
2380 GLenum target,
2381 GLint level,
2382 GLint xoffset,
2383 GLint yoffset,
2384 GLsizei width,
2385 GLsizei height,
2386 GLenum format,
2387 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002388 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002389{
2390
Martin Radev1be913c2016-07-11 17:59:16 +03002391 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002392 {
2393 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002394 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002395 }
2396
Martin Radev1be913c2016-07-11 17:59:16 +03002397 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002398 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002399 yoffset, 0, width, height, 1, 0, format, type, -1,
2400 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002401}
2402
Geoff Langc52f6f12016-10-14 10:18:00 -04002403bool ValidateTexSubImage2DRobustANGLE(Context *context,
2404 GLenum target,
2405 GLint level,
2406 GLint xoffset,
2407 GLint yoffset,
2408 GLsizei width,
2409 GLsizei height,
2410 GLenum format,
2411 GLenum type,
2412 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002413 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002414{
2415 if (!ValidateRobustEntryPoint(context, bufSize))
2416 {
2417 return false;
2418 }
2419
2420 if (context->getClientMajorVersion() < 3)
2421 {
2422 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2423 yoffset, width, height, 0, format, type, bufSize,
2424 pixels);
2425 }
2426
2427 ASSERT(context->getClientMajorVersion() >= 3);
2428 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2429 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2430 pixels);
2431}
2432
Jamie Madill73a84962016-02-12 09:27:23 -05002433bool ValidateCompressedTexImage2D(Context *context,
2434 GLenum target,
2435 GLint level,
2436 GLenum internalformat,
2437 GLsizei width,
2438 GLsizei height,
2439 GLint border,
2440 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002441 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002442{
Martin Radev1be913c2016-07-11 17:59:16 +03002443 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002444 {
2445 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002446 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002447 {
2448 return false;
2449 }
2450 }
2451 else
2452 {
Martin Radev1be913c2016-07-11 17:59:16 +03002453 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002454 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002455 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002456 data))
2457 {
2458 return false;
2459 }
2460 }
2461
Geoff Langca271392017-04-05 12:30:00 -04002462 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002463 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002464 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002465 if (blockSizeOrErr.isError())
2466 {
2467 context->handleError(blockSizeOrErr.getError());
2468 return false;
2469 }
2470
2471 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002473 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002474 return false;
2475 }
2476
2477 return true;
2478}
2479
Corentin Wallezb2931602017-04-11 15:58:57 -04002480bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2481 GLenum target,
2482 GLint level,
2483 GLenum internalformat,
2484 GLsizei width,
2485 GLsizei height,
2486 GLint border,
2487 GLsizei imageSize,
2488 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002489 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002490{
2491 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2492 {
2493 return false;
2494 }
2495
2496 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2497 border, imageSize, data);
2498}
2499bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2500 GLenum target,
2501 GLint level,
2502 GLint xoffset,
2503 GLint yoffset,
2504 GLsizei width,
2505 GLsizei height,
2506 GLenum format,
2507 GLsizei imageSize,
2508 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002509 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002510{
2511 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2512 {
2513 return false;
2514 }
2515
2516 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2517 format, imageSize, data);
2518}
2519
Jamie Madill73a84962016-02-12 09:27:23 -05002520bool ValidateCompressedTexSubImage2D(Context *context,
2521 GLenum target,
2522 GLint level,
2523 GLint xoffset,
2524 GLint yoffset,
2525 GLsizei width,
2526 GLsizei height,
2527 GLenum format,
2528 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002529 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002530{
Martin Radev1be913c2016-07-11 17:59:16 +03002531 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002532 {
2533 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002534 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002535 {
2536 return false;
2537 }
2538 }
2539 else
2540 {
Martin Radev1be913c2016-07-11 17:59:16 +03002541 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002542 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002543 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002544 data))
2545 {
2546 return false;
2547 }
2548 }
2549
Geoff Langca271392017-04-05 12:30:00 -04002550 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002551 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002552 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002553 if (blockSizeOrErr.isError())
2554 {
2555 context->handleError(blockSizeOrErr.getError());
2556 return false;
2557 }
2558
2559 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002561 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002562 return false;
2563 }
2564
2565 return true;
2566}
2567
Olli Etuaho4f667482016-03-30 15:56:35 +03002568bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2569{
Geoff Lang496c02d2016-10-20 11:38:11 -07002570 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002571}
2572
2573bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2574{
2575 if (!context->getExtensions().mapBuffer)
2576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002577 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002578 return false;
2579 }
2580
2581 if (!ValidBufferTarget(context, target))
2582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002583 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002584 return false;
2585 }
2586
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002587 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002588
2589 if (buffer == nullptr)
2590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002591 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002592 return false;
2593 }
2594
2595 if (access != GL_WRITE_ONLY_OES)
2596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002597 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002598 return false;
2599 }
2600
2601 if (buffer->isMapped())
2602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002603 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002604 return false;
2605 }
2606
2607 return true;
2608}
2609
2610bool ValidateUnmapBufferOES(Context *context, GLenum target)
2611{
2612 if (!context->getExtensions().mapBuffer)
2613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002614 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002615 return false;
2616 }
2617
2618 return ValidateUnmapBufferBase(context, target);
2619}
2620
2621bool ValidateMapBufferRangeEXT(Context *context,
2622 GLenum target,
2623 GLintptr offset,
2624 GLsizeiptr length,
2625 GLbitfield access)
2626{
2627 if (!context->getExtensions().mapBufferRange)
2628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002629 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002630 return false;
2631 }
2632
2633 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2634}
2635
2636bool ValidateFlushMappedBufferRangeEXT(Context *context,
2637 GLenum target,
2638 GLintptr offset,
2639 GLsizeiptr length)
2640{
2641 if (!context->getExtensions().mapBufferRange)
2642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002643 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002644 return false;
2645 }
2646
2647 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2648}
2649
Ian Ewell54f87462016-03-10 13:47:21 -05002650bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2651{
2652 Texture *textureObject = context->getTexture(texture);
2653 if (textureObject && textureObject->getTarget() != target && texture != 0)
2654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002655 context->handleError(InvalidOperation() << "Invalid texture");
Ian Ewell54f87462016-03-10 13:47:21 -05002656 return false;
2657 }
2658
Geoff Langf41a7152016-09-19 15:11:17 -04002659 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2660 !context->isTextureGenerated(texture))
2661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002662 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002663 return false;
2664 }
2665
Ian Ewell54f87462016-03-10 13:47:21 -05002666 switch (target)
2667 {
2668 case GL_TEXTURE_2D:
2669 case GL_TEXTURE_CUBE_MAP:
2670 break;
2671
2672 case GL_TEXTURE_3D:
2673 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002674 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002676 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002677 return false;
2678 }
2679 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002680
2681 case GL_TEXTURE_2D_MULTISAMPLE:
2682 if (context->getClientVersion() < Version(3, 1))
2683 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002684 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002685 return false;
2686 }
Geoff Lang3b573612016-10-31 14:08:10 -04002687 break;
2688
Ian Ewell54f87462016-03-10 13:47:21 -05002689 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002690 if (!context->getExtensions().eglImageExternal &&
2691 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002693 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002694 return false;
2695 }
2696 break;
2697 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002698 context->handleError(InvalidEnum() << "Invalid target");
Ian Ewell54f87462016-03-10 13:47:21 -05002699 return false;
2700 }
2701
2702 return true;
2703}
2704
Geoff Langd8605522016-04-13 10:19:12 -04002705bool ValidateBindUniformLocationCHROMIUM(Context *context,
2706 GLuint program,
2707 GLint location,
2708 const GLchar *name)
2709{
2710 if (!context->getExtensions().bindUniformLocation)
2711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002712 context->handleError(InvalidOperation()
2713 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002714 return false;
2715 }
2716
2717 Program *programObject = GetValidProgram(context, program);
2718 if (!programObject)
2719 {
2720 return false;
2721 }
2722
2723 if (location < 0)
2724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002725 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002726 return false;
2727 }
2728
2729 const Caps &caps = context->getCaps();
2730 if (static_cast<size_t>(location) >=
2731 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002733 context->handleError(InvalidValue() << "Location must be less than "
2734 "(MAX_VERTEX_UNIFORM_VECTORS + "
2735 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002736 return false;
2737 }
2738
Geoff Langfc32e8b2017-05-31 14:16:59 -04002739 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2740 // shader-related entry points
2741 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
2742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002743 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04002744 return false;
2745 }
2746
Geoff Langd8605522016-04-13 10:19:12 -04002747 if (strncmp(name, "gl_", 3) == 0)
2748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002749 context->handleError(InvalidOperation()
2750 << "Name cannot start with the reserved \"gl_\" prefix.");
Geoff Langd8605522016-04-13 10:19:12 -04002751 return false;
2752 }
2753
2754 return true;
2755}
2756
Jamie Madille2e406c2016-06-02 13:04:10 -04002757bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002758{
2759 if (!context->getExtensions().framebufferMixedSamples)
2760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002761 context->handleError(InvalidOperation()
2762 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002763 return false;
2764 }
2765 switch (components)
2766 {
2767 case GL_RGB:
2768 case GL_RGBA:
2769 case GL_ALPHA:
2770 case GL_NONE:
2771 break;
2772 default:
2773 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002774 InvalidEnum()
2775 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002776 return false;
2777 }
2778
2779 return true;
2780}
2781
Sami Väisänene45e53b2016-05-25 10:36:04 +03002782// CHROMIUM_path_rendering
2783
2784bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2785{
2786 if (!context->getExtensions().pathRendering)
2787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002788 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002789 return false;
2790 }
2791 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002793 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002794 return false;
2795 }
2796 if (matrix == nullptr)
2797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002798 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002799 return false;
2800 }
2801 return true;
2802}
2803
2804bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2805{
2806 if (!context->getExtensions().pathRendering)
2807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002808 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002809 return false;
2810 }
2811 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002813 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002814 return false;
2815 }
2816 return true;
2817}
2818
2819bool ValidateGenPaths(Context *context, GLsizei range)
2820{
2821 if (!context->getExtensions().pathRendering)
2822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002823 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002824 return false;
2825 }
2826
2827 // range = 0 is undefined in NV_path_rendering.
2828 // we add stricter semantic check here and require a non zero positive range.
2829 if (range <= 0)
2830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002831 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002832 return false;
2833 }
2834
2835 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002837 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002838 return false;
2839 }
2840
2841 return true;
2842}
2843
2844bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2845{
2846 if (!context->getExtensions().pathRendering)
2847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002848 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002849 return false;
2850 }
2851
2852 // range = 0 is undefined in NV_path_rendering.
2853 // we add stricter semantic check here and require a non zero positive range.
2854 if (range <= 0)
2855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002856 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002857 return false;
2858 }
2859
2860 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2861 checkedRange += range;
2862
2863 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002865 context->handleError(InvalidOperation() << "Range overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002866 return false;
2867 }
2868 return true;
2869}
2870
2871bool ValidatePathCommands(Context *context,
2872 GLuint path,
2873 GLsizei numCommands,
2874 const GLubyte *commands,
2875 GLsizei numCoords,
2876 GLenum coordType,
2877 const void *coords)
2878{
2879 if (!context->getExtensions().pathRendering)
2880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002881 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002882 return false;
2883 }
2884 if (!context->hasPath(path))
2885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002886 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002887 return false;
2888 }
2889
2890 if (numCommands < 0)
2891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002892 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002893 return false;
2894 }
2895 else if (numCommands > 0)
2896 {
2897 if (!commands)
2898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002899 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002900 return false;
2901 }
2902 }
2903
2904 if (numCoords < 0)
2905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002906 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002907 return false;
2908 }
2909 else if (numCoords > 0)
2910 {
2911 if (!coords)
2912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002913 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002914 return false;
2915 }
2916 }
2917
2918 std::uint32_t coordTypeSize = 0;
2919 switch (coordType)
2920 {
2921 case GL_BYTE:
2922 coordTypeSize = sizeof(GLbyte);
2923 break;
2924
2925 case GL_UNSIGNED_BYTE:
2926 coordTypeSize = sizeof(GLubyte);
2927 break;
2928
2929 case GL_SHORT:
2930 coordTypeSize = sizeof(GLshort);
2931 break;
2932
2933 case GL_UNSIGNED_SHORT:
2934 coordTypeSize = sizeof(GLushort);
2935 break;
2936
2937 case GL_FLOAT:
2938 coordTypeSize = sizeof(GLfloat);
2939 break;
2940
2941 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002942 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002943 return false;
2944 }
2945
2946 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2947 checkedSize += (coordTypeSize * numCoords);
2948 if (!checkedSize.IsValid())
2949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002950 context->handleError(InvalidOperation() << "Coord size overflow.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002951 return false;
2952 }
2953
2954 // early return skips command data validation when it doesn't exist.
2955 if (!commands)
2956 return true;
2957
2958 GLsizei expectedNumCoords = 0;
2959 for (GLsizei i = 0; i < numCommands; ++i)
2960 {
2961 switch (commands[i])
2962 {
2963 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2964 break;
2965 case GL_MOVE_TO_CHROMIUM:
2966 case GL_LINE_TO_CHROMIUM:
2967 expectedNumCoords += 2;
2968 break;
2969 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2970 expectedNumCoords += 4;
2971 break;
2972 case GL_CUBIC_CURVE_TO_CHROMIUM:
2973 expectedNumCoords += 6;
2974 break;
2975 case GL_CONIC_CURVE_TO_CHROMIUM:
2976 expectedNumCoords += 5;
2977 break;
2978 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002979 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002980 return false;
2981 }
2982 }
2983 if (expectedNumCoords != numCoords)
2984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002985 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002986 return false;
2987 }
2988
2989 return true;
2990}
2991
2992bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2993{
2994 if (!context->getExtensions().pathRendering)
2995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002996 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002997 return false;
2998 }
2999 if (!context->hasPath(path))
3000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003001 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003002 return false;
3003 }
3004
3005 switch (pname)
3006 {
3007 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3008 if (value < 0.0f)
3009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003010 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003011 return false;
3012 }
3013 break;
3014 case GL_PATH_END_CAPS_CHROMIUM:
3015 switch (static_cast<GLenum>(value))
3016 {
3017 case GL_FLAT_CHROMIUM:
3018 case GL_SQUARE_CHROMIUM:
3019 case GL_ROUND_CHROMIUM:
3020 break;
3021 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003022 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003023 return false;
3024 }
3025 break;
3026 case GL_PATH_JOIN_STYLE_CHROMIUM:
3027 switch (static_cast<GLenum>(value))
3028 {
3029 case GL_MITER_REVERT_CHROMIUM:
3030 case GL_BEVEL_CHROMIUM:
3031 case GL_ROUND_CHROMIUM:
3032 break;
3033 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003034 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003035 return false;
3036 }
3037 case GL_PATH_MITER_LIMIT_CHROMIUM:
3038 if (value < 0.0f)
3039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003040 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003041 return false;
3042 }
3043 break;
3044
3045 case GL_PATH_STROKE_BOUND_CHROMIUM:
3046 // no errors, only clamping.
3047 break;
3048
3049 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003050 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003051 return false;
3052 }
3053 return true;
3054}
3055
3056bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3057{
3058 if (!context->getExtensions().pathRendering)
3059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003060 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003061 return false;
3062 }
3063
3064 if (!context->hasPath(path))
3065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003066 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003067 return false;
3068 }
3069 if (!value)
3070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003071 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003072 return false;
3073 }
3074
3075 switch (pname)
3076 {
3077 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3078 case GL_PATH_END_CAPS_CHROMIUM:
3079 case GL_PATH_JOIN_STYLE_CHROMIUM:
3080 case GL_PATH_MITER_LIMIT_CHROMIUM:
3081 case GL_PATH_STROKE_BOUND_CHROMIUM:
3082 break;
3083
3084 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003085 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003086 return false;
3087 }
3088
3089 return true;
3090}
3091
3092bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3093{
3094 if (!context->getExtensions().pathRendering)
3095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003096 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003097 return false;
3098 }
3099
3100 switch (func)
3101 {
3102 case GL_NEVER:
3103 case GL_ALWAYS:
3104 case GL_LESS:
3105 case GL_LEQUAL:
3106 case GL_EQUAL:
3107 case GL_GEQUAL:
3108 case GL_GREATER:
3109 case GL_NOTEQUAL:
3110 break;
3111 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003112 context->handleError(InvalidEnum() << "Invalid stencil function.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003113 return false;
3114 }
3115
3116 return true;
3117}
3118
3119// Note that the spec specifies that for the path drawing commands
3120// if the path object is not an existing path object the command
3121// does nothing and no error is generated.
3122// However if the path object exists but has not been specified any
3123// commands then an error is generated.
3124
3125bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3126{
3127 if (!context->getExtensions().pathRendering)
3128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003129 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003130 return false;
3131 }
3132 if (context->hasPath(path) && !context->hasPathData(path))
3133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003134 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003135 return false;
3136 }
3137
3138 switch (fillMode)
3139 {
3140 case GL_COUNT_UP_CHROMIUM:
3141 case GL_COUNT_DOWN_CHROMIUM:
3142 break;
3143 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003144 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003145 return false;
3146 }
3147
3148 if (!isPow2(mask + 1))
3149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003150 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003151 return false;
3152 }
3153
3154 return true;
3155}
3156
3157bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3158{
3159 if (!context->getExtensions().pathRendering)
3160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003161 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003162 return false;
3163 }
3164 if (context->hasPath(path) && !context->hasPathData(path))
3165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003166 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003167 return false;
3168 }
3169
3170 return true;
3171}
3172
3173bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3174{
3175 if (!context->getExtensions().pathRendering)
3176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003177 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003178 return false;
3179 }
3180 if (context->hasPath(path) && !context->hasPathData(path))
3181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003182 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003183 return false;
3184 }
3185
3186 switch (coverMode)
3187 {
3188 case GL_CONVEX_HULL_CHROMIUM:
3189 case GL_BOUNDING_BOX_CHROMIUM:
3190 break;
3191 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003192 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003193 return false;
3194 }
3195 return true;
3196}
3197
3198bool ValidateStencilThenCoverFillPath(Context *context,
3199 GLuint path,
3200 GLenum fillMode,
3201 GLuint mask,
3202 GLenum coverMode)
3203{
3204 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3205 ValidateCoverPath(context, path, coverMode);
3206}
3207
3208bool ValidateStencilThenCoverStrokePath(Context *context,
3209 GLuint path,
3210 GLint reference,
3211 GLuint mask,
3212 GLenum coverMode)
3213{
3214 return ValidateStencilStrokePath(context, path, reference, mask) &&
3215 ValidateCoverPath(context, path, coverMode);
3216}
3217
3218bool ValidateIsPath(Context *context)
3219{
3220 if (!context->getExtensions().pathRendering)
3221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003222 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003223 return false;
3224 }
3225 return true;
3226}
3227
Sami Väisänend59ca052016-06-21 16:10:00 +03003228bool ValidateCoverFillPathInstanced(Context *context,
3229 GLsizei numPaths,
3230 GLenum pathNameType,
3231 const void *paths,
3232 GLuint pathBase,
3233 GLenum coverMode,
3234 GLenum transformType,
3235 const GLfloat *transformValues)
3236{
3237 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3238 transformType, transformValues))
3239 return false;
3240
3241 switch (coverMode)
3242 {
3243 case GL_CONVEX_HULL_CHROMIUM:
3244 case GL_BOUNDING_BOX_CHROMIUM:
3245 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3246 break;
3247 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003248 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003249 return false;
3250 }
3251
3252 return true;
3253}
3254
3255bool ValidateCoverStrokePathInstanced(Context *context,
3256 GLsizei numPaths,
3257 GLenum pathNameType,
3258 const void *paths,
3259 GLuint pathBase,
3260 GLenum coverMode,
3261 GLenum transformType,
3262 const GLfloat *transformValues)
3263{
3264 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3265 transformType, transformValues))
3266 return false;
3267
3268 switch (coverMode)
3269 {
3270 case GL_CONVEX_HULL_CHROMIUM:
3271 case GL_BOUNDING_BOX_CHROMIUM:
3272 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3273 break;
3274 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003275 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003276 return false;
3277 }
3278
3279 return true;
3280}
3281
3282bool ValidateStencilFillPathInstanced(Context *context,
3283 GLsizei numPaths,
3284 GLenum pathNameType,
3285 const void *paths,
3286 GLuint pathBase,
3287 GLenum fillMode,
3288 GLuint mask,
3289 GLenum transformType,
3290 const GLfloat *transformValues)
3291{
3292
3293 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3294 transformType, transformValues))
3295 return false;
3296
3297 switch (fillMode)
3298 {
3299 case GL_COUNT_UP_CHROMIUM:
3300 case GL_COUNT_DOWN_CHROMIUM:
3301 break;
3302 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003303 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003304 return false;
3305 }
3306 if (!isPow2(mask + 1))
3307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003308 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003309 return false;
3310 }
3311 return true;
3312}
3313
3314bool ValidateStencilStrokePathInstanced(Context *context,
3315 GLsizei numPaths,
3316 GLenum pathNameType,
3317 const void *paths,
3318 GLuint pathBase,
3319 GLint reference,
3320 GLuint mask,
3321 GLenum transformType,
3322 const GLfloat *transformValues)
3323{
3324 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3325 transformType, transformValues))
3326 return false;
3327
3328 // no more validation here.
3329
3330 return true;
3331}
3332
3333bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3334 GLsizei numPaths,
3335 GLenum pathNameType,
3336 const void *paths,
3337 GLuint pathBase,
3338 GLenum fillMode,
3339 GLuint mask,
3340 GLenum coverMode,
3341 GLenum transformType,
3342 const GLfloat *transformValues)
3343{
3344 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3345 transformType, transformValues))
3346 return false;
3347
3348 switch (coverMode)
3349 {
3350 case GL_CONVEX_HULL_CHROMIUM:
3351 case GL_BOUNDING_BOX_CHROMIUM:
3352 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3353 break;
3354 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003355 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003356 return false;
3357 }
3358
3359 switch (fillMode)
3360 {
3361 case GL_COUNT_UP_CHROMIUM:
3362 case GL_COUNT_DOWN_CHROMIUM:
3363 break;
3364 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003365 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003366 return false;
3367 }
3368 if (!isPow2(mask + 1))
3369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003370 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003371 return false;
3372 }
3373
3374 return true;
3375}
3376
3377bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3378 GLsizei numPaths,
3379 GLenum pathNameType,
3380 const void *paths,
3381 GLuint pathBase,
3382 GLint reference,
3383 GLuint mask,
3384 GLenum coverMode,
3385 GLenum transformType,
3386 const GLfloat *transformValues)
3387{
3388 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3389 transformType, transformValues))
3390 return false;
3391
3392 switch (coverMode)
3393 {
3394 case GL_CONVEX_HULL_CHROMIUM:
3395 case GL_BOUNDING_BOX_CHROMIUM:
3396 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3397 break;
3398 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003399 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003400 return false;
3401 }
3402
3403 return true;
3404}
3405
Sami Väisänen46eaa942016-06-29 10:26:37 +03003406bool ValidateBindFragmentInputLocation(Context *context,
3407 GLuint program,
3408 GLint location,
3409 const GLchar *name)
3410{
3411 if (!context->getExtensions().pathRendering)
3412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003413 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003414 return false;
3415 }
3416
3417 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3418 if (location >= MaxLocation)
3419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003420 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003421 return false;
3422 }
3423
3424 const auto *programObject = context->getProgram(program);
3425 if (!programObject)
3426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003427 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003428 return false;
3429 }
3430
3431 if (!name)
3432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003433 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003434 return false;
3435 }
3436
3437 if (angle::BeginsWith(name, "gl_"))
3438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003439 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003440 return false;
3441 }
3442
3443 return true;
3444}
3445
3446bool ValidateProgramPathFragmentInputGen(Context *context,
3447 GLuint program,
3448 GLint location,
3449 GLenum genMode,
3450 GLint components,
3451 const GLfloat *coeffs)
3452{
3453 if (!context->getExtensions().pathRendering)
3454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003455 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003456 return false;
3457 }
3458
3459 const auto *programObject = context->getProgram(program);
3460 if (!programObject || programObject->isFlaggedForDeletion())
3461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003462 context->handleError(InvalidOperation() << "No such program.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003463 return false;
3464 }
3465
3466 if (!programObject->isLinked())
3467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003468 context->handleError(InvalidOperation() << "Program is not linked.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003469 return false;
3470 }
3471
3472 switch (genMode)
3473 {
3474 case GL_NONE:
3475 if (components != 0)
3476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003477 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003478 return false;
3479 }
3480 break;
3481
3482 case GL_OBJECT_LINEAR_CHROMIUM:
3483 case GL_EYE_LINEAR_CHROMIUM:
3484 case GL_CONSTANT_CHROMIUM:
3485 if (components < 1 || components > 4)
3486 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003487 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003488 return false;
3489 }
3490 if (!coeffs)
3491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003492 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003493 return false;
3494 }
3495 break;
3496
3497 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003498 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003499 return false;
3500 }
3501
3502 // If the location is -1 then the command is silently ignored
3503 // and no further validation is needed.
3504 if (location == -1)
3505 return true;
3506
Jamie Madillbd044ed2017-06-05 12:59:21 -04003507 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003508
3509 if (!binding.valid)
3510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003511 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003512 return false;
3513 }
3514
3515 if (binding.type != GL_NONE)
3516 {
3517 GLint expectedComponents = 0;
3518 switch (binding.type)
3519 {
3520 case GL_FLOAT:
3521 expectedComponents = 1;
3522 break;
3523 case GL_FLOAT_VEC2:
3524 expectedComponents = 2;
3525 break;
3526 case GL_FLOAT_VEC3:
3527 expectedComponents = 3;
3528 break;
3529 case GL_FLOAT_VEC4:
3530 expectedComponents = 4;
3531 break;
3532 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003533 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003534 InvalidOperation()
3535 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003536 return false;
3537 }
3538 if (expectedComponents != components && genMode != GL_NONE)
3539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003540 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003541 return false;
3542 }
3543 }
3544 return true;
3545}
3546
Geoff Lang97073d12016-04-20 10:42:34 -07003547bool ValidateCopyTextureCHROMIUM(Context *context,
3548 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003549 GLint sourceLevel,
3550 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003551 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003552 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003553 GLint internalFormat,
3554 GLenum destType,
3555 GLboolean unpackFlipY,
3556 GLboolean unpackPremultiplyAlpha,
3557 GLboolean unpackUnmultiplyAlpha)
3558{
3559 if (!context->getExtensions().copyTexture)
3560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003561 context->handleError(InvalidOperation()
3562 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003563 return false;
3564 }
3565
Geoff Lang4f0e0032017-05-01 16:04:35 -04003566 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003567 if (source == nullptr)
3568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003569 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003570 return false;
3571 }
3572
3573 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003575 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003576 return false;
3577 }
3578
3579 GLenum sourceTarget = source->getTarget();
3580 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003581
3582 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003584 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003585 return false;
3586 }
3587
Geoff Lang4f0e0032017-05-01 16:04:35 -04003588 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3589 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3590 if (sourceWidth == 0 || sourceHeight == 0)
3591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003592 context->handleError(InvalidValue()
3593 << "The source level of the source texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003594 return false;
3595 }
3596
3597 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3598 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003601 return false;
3602 }
3603
Geoff Lang4f0e0032017-05-01 16:04:35 -04003604 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003605 if (dest == nullptr)
3606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003607 context->handleError(InvalidValue()
3608 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003609 return false;
3610 }
3611
Geoff Lang4f0e0032017-05-01 16:04:35 -04003612 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003614 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003615 return false;
3616 }
3617
Geoff Lang4f0e0032017-05-01 16:04:35 -04003618 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3619 sourceHeight))
3620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003622 return false;
3623 }
3624
Geoff Lang97073d12016-04-20 10:42:34 -07003625 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003627 context->handleError(InvalidOperation()
3628 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003629 return false;
3630 }
3631
Geoff Lang4f0e0032017-05-01 16:04:35 -04003632 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003634 context->handleError(
3635 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003636 return false;
3637 }
3638
Geoff Lang97073d12016-04-20 10:42:34 -07003639 if (dest->getImmutableFormat())
3640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003641 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003642 return false;
3643 }
3644
3645 return true;
3646}
3647
3648bool ValidateCopySubTextureCHROMIUM(Context *context,
3649 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003650 GLint sourceLevel,
3651 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003652 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003653 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003654 GLint xoffset,
3655 GLint yoffset,
3656 GLint x,
3657 GLint y,
3658 GLsizei width,
3659 GLsizei height,
3660 GLboolean unpackFlipY,
3661 GLboolean unpackPremultiplyAlpha,
3662 GLboolean unpackUnmultiplyAlpha)
3663{
3664 if (!context->getExtensions().copyTexture)
3665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003666 context->handleError(InvalidOperation()
3667 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003668 return false;
3669 }
3670
Geoff Lang4f0e0032017-05-01 16:04:35 -04003671 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003672 if (source == nullptr)
3673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003674 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003675 return false;
3676 }
3677
3678 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003680 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003681 return false;
3682 }
3683
3684 GLenum sourceTarget = source->getTarget();
3685 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003686
3687 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003689 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003690 return false;
3691 }
3692
3693 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3694 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003696 context->handleError(InvalidValue()
3697 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003698 return false;
3699 }
3700
3701 if (x < 0 || y < 0)
3702 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003703 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003704 return false;
3705 }
3706
3707 if (width < 0 || height < 0)
3708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidValue() << "width and height cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003710 return false;
3711 }
3712
Geoff Lang4f0e0032017-05-01 16:04:35 -04003713 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3714 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(InvalidValue() << "Source texture not large enough to copy from.");
Geoff Lang97073d12016-04-20 10:42:34 -07003717 return false;
3718 }
3719
Geoff Lang4f0e0032017-05-01 16:04:35 -04003720 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3721 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003723 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003724 return false;
3725 }
3726
Geoff Lang4f0e0032017-05-01 16:04:35 -04003727 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003728 if (dest == nullptr)
3729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003730 context->handleError(InvalidValue()
3731 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003732 return false;
3733 }
3734
Geoff Lang4f0e0032017-05-01 16:04:35 -04003735 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003737 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003738 return false;
3739 }
3740
Geoff Lang4f0e0032017-05-01 16:04:35 -04003741 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003744 return false;
3745 }
3746
Geoff Lang4f0e0032017-05-01 16:04:35 -04003747 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003749 context->handleError(
3750 InvalidValue() << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003751 return false;
3752 }
3753
3754 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3755 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003757 context->handleError(InvalidOperation()
3758 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003759 return false;
3760 }
3761
3762 if (xoffset < 0 || yoffset < 0)
3763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(InvalidValue() << "xoffset and yoffset cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003765 return false;
3766 }
3767
Geoff Lang4f0e0032017-05-01 16:04:35 -04003768 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3769 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003772 return false;
3773 }
3774
3775 return true;
3776}
3777
Geoff Lang47110bf2016-04-20 11:13:22 -07003778bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3779{
3780 if (!context->getExtensions().copyCompressedTexture)
3781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(InvalidOperation()
3783 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003784 return false;
3785 }
3786
3787 const gl::Texture *source = context->getTexture(sourceId);
3788 if (source == nullptr)
3789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003791 return false;
3792 }
3793
3794 if (source->getTarget() != GL_TEXTURE_2D)
3795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003797 return false;
3798 }
3799
3800 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003802 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003803 return false;
3804 }
3805
3806 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3807 if (!sourceFormat.info->compressed)
3808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003809 context->handleError(InvalidOperation()
3810 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003811 return false;
3812 }
3813
3814 const gl::Texture *dest = context->getTexture(destId);
3815 if (dest == nullptr)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(InvalidValue()
3818 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003819 return false;
3820 }
3821
3822 if (dest->getTarget() != GL_TEXTURE_2D)
3823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003824 context->handleError(InvalidValue()
3825 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003826 return false;
3827 }
3828
3829 if (dest->getImmutableFormat())
3830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003831 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003832 return false;
3833 }
3834
3835 return true;
3836}
3837
Martin Radev4c4c8e72016-08-04 12:25:34 +03003838bool ValidateCreateShader(Context *context, GLenum type)
3839{
3840 switch (type)
3841 {
3842 case GL_VERTEX_SHADER:
3843 case GL_FRAGMENT_SHADER:
3844 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003845
Martin Radev4c4c8e72016-08-04 12:25:34 +03003846 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003847 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003849 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003850 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003851 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003852 break;
3853
Martin Radev4c4c8e72016-08-04 12:25:34 +03003854 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidEnum() << "Unknown shader type.");
Martin Radev4c4c8e72016-08-04 12:25:34 +03003856 return false;
3857 }
Jamie Madill29639852016-09-02 15:00:09 -04003858
3859 return true;
3860}
3861
3862bool ValidateBufferData(ValidationContext *context,
3863 GLenum target,
3864 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003865 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003866 GLenum usage)
3867{
3868 if (size < 0)
3869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003870 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003871 return false;
3872 }
3873
3874 switch (usage)
3875 {
3876 case GL_STREAM_DRAW:
3877 case GL_STATIC_DRAW:
3878 case GL_DYNAMIC_DRAW:
3879 break;
3880
3881 case GL_STREAM_READ:
3882 case GL_STREAM_COPY:
3883 case GL_STATIC_READ:
3884 case GL_STATIC_COPY:
3885 case GL_DYNAMIC_READ:
3886 case GL_DYNAMIC_COPY:
3887 if (context->getClientMajorVersion() < 3)
3888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003889 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003890 return false;
3891 }
3892 break;
3893
3894 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003896 return false;
3897 }
3898
3899 if (!ValidBufferTarget(context, target))
3900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003901 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003902 return false;
3903 }
3904
3905 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3906
3907 if (!buffer)
3908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003909 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003910 return false;
3911 }
3912
3913 return true;
3914}
3915
3916bool ValidateBufferSubData(ValidationContext *context,
3917 GLenum target,
3918 GLintptr offset,
3919 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003920 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003921{
3922 if (size < 0 || offset < 0)
3923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003925 return false;
3926 }
3927
3928 if (!ValidBufferTarget(context, target))
3929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(InvalidEnum());
Jamie Madill29639852016-09-02 15:00:09 -04003931 return false;
3932 }
3933
3934 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3935
3936 if (!buffer)
3937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003938 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003939 return false;
3940 }
3941
3942 if (buffer->isMapped())
3943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003944 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003945 return false;
3946 }
3947
3948 // Check for possible overflow of size + offset
3949 angle::CheckedNumeric<size_t> checkedSize(size);
3950 checkedSize += offset;
3951 if (!checkedSize.IsValid())
3952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003953 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04003954 return false;
3955 }
3956
3957 if (size + offset > buffer->getSize())
3958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003959 context->handleError(InvalidValue());
Jamie Madill29639852016-09-02 15:00:09 -04003960 return false;
3961 }
3962
Martin Radev4c4c8e72016-08-04 12:25:34 +03003963 return true;
3964}
3965
Geoff Langc339c4e2016-11-29 10:37:36 -05003966bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003967{
Geoff Langc339c4e2016-11-29 10:37:36 -05003968 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003970 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04003971 return false;
3972 }
3973
3974 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3975 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003976 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003978 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04003979 return false;
3980 }
3981
3982 return true;
3983}
3984
Jamie Madillef300b12016-10-07 15:12:09 -04003985bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3986{
3987 if (texture < GL_TEXTURE0 ||
3988 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003990 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04003991 return false;
3992 }
3993
3994 return true;
3995}
3996
3997bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3998{
3999 Program *programObject = GetValidProgram(context, program);
4000 if (!programObject)
4001 {
4002 return false;
4003 }
4004
4005 Shader *shaderObject = GetValidShader(context, shader);
4006 if (!shaderObject)
4007 {
4008 return false;
4009 }
4010
4011 switch (shaderObject->getType())
4012 {
4013 case GL_VERTEX_SHADER:
4014 {
4015 if (programObject->getAttachedVertexShader())
4016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004017 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004018 return false;
4019 }
4020 break;
4021 }
4022 case GL_FRAGMENT_SHADER:
4023 {
4024 if (programObject->getAttachedFragmentShader())
4025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004026 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004027 return false;
4028 }
4029 break;
4030 }
4031 case GL_COMPUTE_SHADER:
4032 {
4033 if (programObject->getAttachedComputeShader())
4034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004035 context->handleError(InvalidOperation());
Jamie Madillef300b12016-10-07 15:12:09 -04004036 return false;
4037 }
4038 break;
4039 }
4040 default:
4041 UNREACHABLE();
4042 break;
4043 }
4044
4045 return true;
4046}
4047
Jamie Madill01a80ee2016-11-07 12:06:18 -05004048bool ValidateBindAttribLocation(ValidationContext *context,
4049 GLuint program,
4050 GLuint index,
4051 const GLchar *name)
4052{
4053 if (index >= MAX_VERTEX_ATTRIBS)
4054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004055 context->handleError(InvalidValue() << "Index exceeds MAX_VERTEX_ATTRIBS");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004056 return false;
4057 }
4058
4059 if (strncmp(name, "gl_", 3) == 0)
4060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidOperation() << "Cannot Bind built-in attributes");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004062 return false;
4063 }
4064
Geoff Langfc32e8b2017-05-31 14:16:59 -04004065 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4066 // shader-related entry points
4067 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004069 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004070 return false;
4071 }
4072
Jamie Madill01a80ee2016-11-07 12:06:18 -05004073 return GetValidProgram(context, program) != nullptr;
4074}
4075
4076bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4077{
4078 if (!ValidBufferTarget(context, target))
4079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004080 context->handleError(InvalidEnum() << "Invalid Buffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004081 return false;
4082 }
4083
4084 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4085 !context->isBufferGenerated(buffer))
4086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004087 context->handleError(InvalidOperation() << "Buffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004088 return false;
4089 }
4090
4091 return true;
4092}
4093
4094bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4095{
4096 if (!ValidFramebufferTarget(target))
4097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004098 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004099 return false;
4100 }
4101
4102 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4103 !context->isFramebufferGenerated(framebuffer))
4104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004105 context->handleError(InvalidOperation() << "Framebuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004106 return false;
4107 }
4108
4109 return true;
4110}
4111
4112bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4113{
4114 if (target != GL_RENDERBUFFER)
4115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004116 context->handleError(InvalidEnum() << "Invalid Renderbuffer target");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004117 return false;
4118 }
4119
4120 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4121 !context->isRenderbufferGenerated(renderbuffer))
4122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004123 context->handleError(InvalidOperation() << "Renderbuffer was not generated");
Jamie Madill01a80ee2016-11-07 12:06:18 -05004124 return false;
4125 }
4126
4127 return true;
4128}
4129
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004130static bool ValidBlendEquationMode(GLenum mode)
4131{
4132 switch (mode)
4133 {
4134 case GL_FUNC_ADD:
4135 case GL_FUNC_SUBTRACT:
4136 case GL_FUNC_REVERSE_SUBTRACT:
4137 case GL_MIN:
4138 case GL_MAX:
4139 return true;
4140
4141 default:
4142 return false;
4143 }
4144}
4145
Jamie Madillc1d770e2017-04-13 17:31:24 -04004146bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004147 GLfloat red,
4148 GLfloat green,
4149 GLfloat blue,
4150 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004151{
4152 return true;
4153}
4154
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004155bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4156{
4157 if (!ValidBlendEquationMode(mode))
4158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004159 context->handleError(InvalidEnum() << "Invalid blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004160 return false;
4161 }
4162
4163 return true;
4164}
4165
4166bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4167{
4168 if (!ValidBlendEquationMode(modeRGB))
4169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004170 context->handleError(InvalidEnum() << "Invalid RGB blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004171 return false;
4172 }
4173
4174 if (!ValidBlendEquationMode(modeAlpha))
4175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004176 context->handleError(InvalidEnum() << "Invalid alpha blend equation");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004177 return false;
4178 }
4179
4180 return true;
4181}
4182
4183bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4184{
4185 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4186}
4187
4188static bool ValidSrcBlendFunc(GLenum srcBlend)
4189{
4190 switch (srcBlend)
4191 {
4192 case GL_ZERO:
4193 case GL_ONE:
4194 case GL_SRC_COLOR:
4195 case GL_ONE_MINUS_SRC_COLOR:
4196 case GL_DST_COLOR:
4197 case GL_ONE_MINUS_DST_COLOR:
4198 case GL_SRC_ALPHA:
4199 case GL_ONE_MINUS_SRC_ALPHA:
4200 case GL_DST_ALPHA:
4201 case GL_ONE_MINUS_DST_ALPHA:
4202 case GL_CONSTANT_COLOR:
4203 case GL_ONE_MINUS_CONSTANT_COLOR:
4204 case GL_CONSTANT_ALPHA:
4205 case GL_ONE_MINUS_CONSTANT_ALPHA:
4206 case GL_SRC_ALPHA_SATURATE:
4207 return true;
4208
4209 default:
4210 return false;
4211 }
4212}
4213
4214static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4215{
4216 switch (dstBlend)
4217 {
4218 case GL_ZERO:
4219 case GL_ONE:
4220 case GL_SRC_COLOR:
4221 case GL_ONE_MINUS_SRC_COLOR:
4222 case GL_DST_COLOR:
4223 case GL_ONE_MINUS_DST_COLOR:
4224 case GL_SRC_ALPHA:
4225 case GL_ONE_MINUS_SRC_ALPHA:
4226 case GL_DST_ALPHA:
4227 case GL_ONE_MINUS_DST_ALPHA:
4228 case GL_CONSTANT_COLOR:
4229 case GL_ONE_MINUS_CONSTANT_COLOR:
4230 case GL_CONSTANT_ALPHA:
4231 case GL_ONE_MINUS_CONSTANT_ALPHA:
4232 return true;
4233
4234 case GL_SRC_ALPHA_SATURATE:
4235 return (contextMajorVersion >= 3);
4236
4237 default:
4238 return false;
4239 }
4240}
4241
4242bool ValidateBlendFuncSeparate(ValidationContext *context,
4243 GLenum srcRGB,
4244 GLenum dstRGB,
4245 GLenum srcAlpha,
4246 GLenum dstAlpha)
4247{
4248 if (!ValidSrcBlendFunc(srcRGB))
4249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004250 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004251 return false;
4252 }
4253
4254 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004256 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004257 return false;
4258 }
4259
4260 if (!ValidSrcBlendFunc(srcAlpha))
4261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004262 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004263 return false;
4264 }
4265
4266 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004268 context->handleError(InvalidEnum() << "Invalid blend function");
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004269 return false;
4270 }
4271
Frank Henigman146e8a12017-03-02 23:22:37 -05004272 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4273 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004274 {
4275 bool constantColorUsed =
4276 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4277 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4278
4279 bool constantAlphaUsed =
4280 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4281 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4282
4283 if (constantColorUsed && constantAlphaUsed)
4284 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004285 const char *msg;
4286 if (context->getExtensions().webglCompatibility)
4287 {
4288 msg =
4289 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4290 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4291 }
4292 else
4293 {
4294 msg =
4295 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4296 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4297 "implementation.";
4298 ERR() << msg;
4299 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004300 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004301 return false;
4302 }
4303 }
4304
4305 return true;
4306}
4307
Geoff Langc339c4e2016-11-29 10:37:36 -05004308bool ValidateGetString(Context *context, GLenum name)
4309{
4310 switch (name)
4311 {
4312 case GL_VENDOR:
4313 case GL_RENDERER:
4314 case GL_VERSION:
4315 case GL_SHADING_LANGUAGE_VERSION:
4316 case GL_EXTENSIONS:
4317 break;
4318
4319 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4320 if (!context->getExtensions().requestExtension)
4321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004322 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004323 return false;
4324 }
4325 break;
4326
4327 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004328 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004329 return false;
4330 }
4331
4332 return true;
4333}
4334
Geoff Lang47c48082016-12-07 15:38:13 -05004335bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4336{
4337 if (width <= 0.0f || isNaN(width))
4338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004339 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004340 return false;
4341 }
4342
4343 return true;
4344}
4345
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004346bool ValidateVertexAttribPointer(ValidationContext *context,
4347 GLuint index,
4348 GLint size,
4349 GLenum type,
4350 GLboolean normalized,
4351 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004352 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004353{
Shao80957d92017-02-20 21:25:59 +08004354 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004355 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004356 return false;
4357 }
4358
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004359 if (stride < 0)
4360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004361 context->handleError(InvalidValue() << "stride cannot be negative.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004362 return false;
4363 }
4364
Shao80957d92017-02-20 21:25:59 +08004365 const Caps &caps = context->getCaps();
4366 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004367 {
Shao80957d92017-02-20 21:25:59 +08004368 if (stride > caps.maxVertexAttribStride)
4369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004370 context->handleError(InvalidValue()
4371 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004372 return false;
4373 }
4374
4375 if (index >= caps.maxVertexAttribBindings)
4376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004377 context->handleError(InvalidValue()
4378 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004379 return false;
4380 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004381 }
4382
4383 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4384 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4385 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4386 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004387 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4388 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004389 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004391 context
4392 ->handleError(InvalidOperation()
4393 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004394 return false;
4395 }
4396
4397 if (context->getExtensions().webglCompatibility)
4398 {
4399 // WebGL 1.0 [Section 6.14] Fixed point support
4400 // The WebGL API does not support the GL_FIXED data type.
4401 if (type == GL_FIXED)
4402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004403 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004404 return false;
4405 }
4406
Geoff Lang2d62ab72017-03-23 16:54:40 -04004407 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004408 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004409 return false;
4410 }
4411 }
4412
4413 return true;
4414}
4415
Jamie Madill876429b2017-04-20 15:46:24 -04004416bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004417{
4418 if (context->getExtensions().webglCompatibility && zNear > zFar)
4419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004420 context->handleError(InvalidOperation() << "Depth near > far.");
Frank Henigman6137ddc2017-02-10 18:55:07 -05004421 return false;
4422 }
4423
4424 return true;
4425}
4426
Jamie Madille8fb6402017-02-14 17:56:40 -05004427bool ValidateRenderbufferStorage(ValidationContext *context,
4428 GLenum target,
4429 GLenum internalformat,
4430 GLsizei width,
4431 GLsizei height)
4432{
4433 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4434 height);
4435}
4436
4437bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4438 GLenum target,
4439 GLsizei samples,
4440 GLenum internalformat,
4441 GLsizei width,
4442 GLsizei height)
4443{
4444 if (!context->getExtensions().framebufferMultisample)
4445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004446 context->handleError(InvalidOperation()
4447 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004448 return false;
4449 }
4450
4451 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4452 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4453 // generated.
4454 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004456 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004457 return false;
4458 }
4459
4460 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4461 // the specified storage. This is different than ES 3.0 in which a sample number higher
4462 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4463 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4464 if (context->getClientMajorVersion() >= 3)
4465 {
4466 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4467 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004469 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004470 return false;
4471 }
4472 }
4473
4474 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4475 width, height);
4476}
4477
Jamie Madillc1d770e2017-04-13 17:31:24 -04004478bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4479{
4480 if (!ValidFramebufferTarget(target))
4481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004482 context->handleError(InvalidEnum() << "Invalid Framebuffer target");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004483 return false;
4484 }
4485
4486 return true;
4487}
4488
4489bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004490 GLfloat red,
4491 GLfloat green,
4492 GLfloat blue,
4493 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004494{
4495 return true;
4496}
4497
Jamie Madill876429b2017-04-20 15:46:24 -04004498bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004499{
4500 return true;
4501}
4502
4503bool ValidateClearStencil(ValidationContext *context, GLint s)
4504{
4505 return true;
4506}
4507
4508bool ValidateColorMask(ValidationContext *context,
4509 GLboolean red,
4510 GLboolean green,
4511 GLboolean blue,
4512 GLboolean alpha)
4513{
4514 return true;
4515}
4516
4517bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4518{
4519 return true;
4520}
4521
4522bool ValidateCreateProgram(ValidationContext *context)
4523{
4524 return true;
4525}
4526
4527bool ValidateCullFace(ValidationContext *context, GLenum mode)
4528{
4529 switch (mode)
4530 {
4531 case GL_FRONT:
4532 case GL_BACK:
4533 case GL_FRONT_AND_BACK:
4534 break;
4535
4536 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004537 context->handleError(InvalidEnum() << "Invalid cull face parameter");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004538 return false;
4539 }
4540
4541 return true;
4542}
4543
4544bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4545{
4546 if (program == 0)
4547 {
4548 return false;
4549 }
4550
4551 if (!context->getProgram(program))
4552 {
4553 if (context->getShader(program))
4554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004555 context->handleError(InvalidOperation() << "Shader handle passed to DeleteProgram");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004556 return false;
4557 }
4558 else
4559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004560 context->handleError(InvalidValue() << "Invalid program handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004561 return false;
4562 }
4563 }
4564
4565 return true;
4566}
4567
4568bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4569{
4570 if (shader == 0)
4571 {
4572 return false;
4573 }
4574
4575 if (!context->getShader(shader))
4576 {
4577 if (context->getProgram(shader))
4578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004579 context->handleError(InvalidOperation() << "Program handle passed to DeleteShader");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004580 return false;
4581 }
4582 else
4583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004584 context->handleError(InvalidValue() << "Invalid shader handle");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004585 return false;
4586 }
4587 }
4588
4589 return true;
4590}
4591
4592bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4593{
4594 switch (func)
4595 {
4596 case GL_NEVER:
4597 case GL_ALWAYS:
4598 case GL_LESS:
4599 case GL_LEQUAL:
4600 case GL_EQUAL:
4601 case GL_GREATER:
4602 case GL_GEQUAL:
4603 case GL_NOTEQUAL:
4604 break;
4605
4606 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004607 context->handleError(InvalidEnum() << "Invalid depth function");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004608 return false;
4609 }
4610
4611 return true;
4612}
4613
4614bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4615{
4616 return true;
4617}
4618
4619bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4620{
4621 Program *programObject = GetValidProgram(context, program);
4622 if (!programObject)
4623 {
4624 return false;
4625 }
4626
4627 Shader *shaderObject = GetValidShader(context, shader);
4628 if (!shaderObject)
4629 {
4630 return false;
4631 }
4632
4633 const Shader *attachedShader = nullptr;
4634
4635 switch (shaderObject->getType())
4636 {
4637 case GL_VERTEX_SHADER:
4638 {
4639 attachedShader = programObject->getAttachedVertexShader();
4640 break;
4641 }
4642 case GL_FRAGMENT_SHADER:
4643 {
4644 attachedShader = programObject->getAttachedFragmentShader();
4645 break;
4646 }
4647 case GL_COMPUTE_SHADER:
4648 {
4649 attachedShader = programObject->getAttachedComputeShader();
4650 break;
4651 }
4652 default:
4653 UNREACHABLE();
4654 return false;
4655 }
4656
4657 if (attachedShader != shaderObject)
4658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004659 context->handleError(InvalidOperation() << "Cannot detach non-attached shader.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004660 return false;
4661 }
4662
4663 return true;
4664}
4665
4666bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4667{
4668 if (index >= MAX_VERTEX_ATTRIBS)
4669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004670 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004671 return false;
4672 }
4673
4674 return true;
4675}
4676
4677bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4678{
4679 if (index >= MAX_VERTEX_ATTRIBS)
4680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004681 context->handleError(InvalidValue() << "Attrib array index out of range");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004682 return false;
4683 }
4684
4685 return true;
4686}
4687
4688bool ValidateFinish(ValidationContext *context)
4689{
4690 return true;
4691}
4692
4693bool ValidateFlush(ValidationContext *context)
4694{
4695 return true;
4696}
4697
4698bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4699{
4700 switch (mode)
4701 {
4702 case GL_CW:
4703 case GL_CCW:
4704 break;
4705 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004706 context->handleError(InvalidEnum() << "Invalid mode for FrontFace");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004707 return false;
4708 }
4709
4710 return true;
4711}
4712
4713bool ValidateGetActiveAttrib(ValidationContext *context,
4714 GLuint program,
4715 GLuint index,
4716 GLsizei bufsize,
4717 GLsizei *length,
4718 GLint *size,
4719 GLenum *type,
4720 GLchar *name)
4721{
4722 if (bufsize < 0)
4723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004724 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004725 return false;
4726 }
4727
4728 Program *programObject = GetValidProgram(context, program);
4729
4730 if (!programObject)
4731 {
4732 return false;
4733 }
4734
4735 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004737 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004738 return false;
4739 }
4740
4741 return true;
4742}
4743
4744bool ValidateGetActiveUniform(ValidationContext *context,
4745 GLuint program,
4746 GLuint index,
4747 GLsizei bufsize,
4748 GLsizei *length,
4749 GLint *size,
4750 GLenum *type,
4751 GLchar *name)
4752{
4753 if (bufsize < 0)
4754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004755 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004756 return false;
4757 }
4758
4759 Program *programObject = GetValidProgram(context, program);
4760
4761 if (!programObject)
4762 {
4763 return false;
4764 }
4765
4766 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004768 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004769 return false;
4770 }
4771
4772 return true;
4773}
4774
4775bool ValidateGetAttachedShaders(ValidationContext *context,
4776 GLuint program,
4777 GLsizei maxcount,
4778 GLsizei *count,
4779 GLuint *shaders)
4780{
4781 if (maxcount < 0)
4782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004783 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004784 return false;
4785 }
4786
4787 Program *programObject = GetValidProgram(context, program);
4788
4789 if (!programObject)
4790 {
4791 return false;
4792 }
4793
4794 return true;
4795}
4796
4797bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4798{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004799 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4800 // shader-related entry points
4801 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004803 context->handleError(InvalidValue() << "Attribute name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004804 return false;
4805 }
4806
Jamie Madillc1d770e2017-04-13 17:31:24 -04004807 Program *programObject = GetValidProgram(context, program);
4808
4809 if (!programObject)
4810 {
4811 return false;
4812 }
4813
4814 if (!programObject->isLinked())
4815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004816 context->handleError(InvalidOperation() << "program not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004817 return false;
4818 }
4819
4820 return true;
4821}
4822
4823bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4824{
4825 GLenum nativeType;
4826 unsigned int numParams = 0;
4827 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4828}
4829
4830bool ValidateGetError(ValidationContext *context)
4831{
4832 return true;
4833}
4834
4835bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4836{
4837 GLenum nativeType;
4838 unsigned int numParams = 0;
4839 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4840}
4841
4842bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4843{
4844 GLenum nativeType;
4845 unsigned int numParams = 0;
4846 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4847}
4848
4849bool ValidateGetProgramInfoLog(ValidationContext *context,
4850 GLuint program,
4851 GLsizei bufsize,
4852 GLsizei *length,
4853 GLchar *infolog)
4854{
4855 if (bufsize < 0)
4856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004857 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004858 return false;
4859 }
4860
4861 Program *programObject = GetValidProgram(context, program);
4862 if (!programObject)
4863 {
4864 return false;
4865 }
4866
4867 return true;
4868}
4869
4870bool ValidateGetShaderInfoLog(ValidationContext *context,
4871 GLuint shader,
4872 GLsizei bufsize,
4873 GLsizei *length,
4874 GLchar *infolog)
4875{
4876 if (bufsize < 0)
4877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004878 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004879 return false;
4880 }
4881
4882 Shader *shaderObject = GetValidShader(context, shader);
4883 if (!shaderObject)
4884 {
4885 return false;
4886 }
4887
4888 return true;
4889}
4890
4891bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4892 GLenum shadertype,
4893 GLenum precisiontype,
4894 GLint *range,
4895 GLint *precision)
4896{
4897 switch (shadertype)
4898 {
4899 case GL_VERTEX_SHADER:
4900 case GL_FRAGMENT_SHADER:
4901 break;
4902 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004903 context->handleError(InvalidOperation()
4904 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004905 return false;
4906 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004907 context->handleError(InvalidEnum() << "invalid shader type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004908 return false;
4909 }
4910
4911 switch (precisiontype)
4912 {
4913 case GL_LOW_FLOAT:
4914 case GL_MEDIUM_FLOAT:
4915 case GL_HIGH_FLOAT:
4916 case GL_LOW_INT:
4917 case GL_MEDIUM_INT:
4918 case GL_HIGH_INT:
4919 break;
4920
4921 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004922 context->handleError(InvalidEnum() << "invalid precision type.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004923 return false;
4924 }
4925
4926 return true;
4927}
4928
4929bool ValidateGetShaderSource(ValidationContext *context,
4930 GLuint shader,
4931 GLsizei bufsize,
4932 GLsizei *length,
4933 GLchar *source)
4934{
4935 if (bufsize < 0)
4936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004937 context->handleError(InvalidValue() << "bufsize must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004938 return false;
4939 }
4940
4941 Shader *shaderObject = GetValidShader(context, shader);
4942 if (!shaderObject)
4943 {
4944 return false;
4945 }
4946
4947 return true;
4948}
4949
4950bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4951{
4952 if (strstr(name, "gl_") == name)
4953 {
4954 return false;
4955 }
4956
Geoff Langfc32e8b2017-05-31 14:16:59 -04004957 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4958 // shader-related entry points
4959 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004961 context->handleError(InvalidValue() << "Uniform name contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04004962 return false;
4963 }
4964
Jamie Madillc1d770e2017-04-13 17:31:24 -04004965 Program *programObject = GetValidProgram(context, program);
4966
4967 if (!programObject)
4968 {
4969 return false;
4970 }
4971
4972 if (!programObject->isLinked())
4973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004974 context->handleError(InvalidOperation() << "program is not linked.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004975 return false;
4976 }
4977
4978 return true;
4979}
4980
4981bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4982{
4983 switch (mode)
4984 {
4985 case GL_FASTEST:
4986 case GL_NICEST:
4987 case GL_DONT_CARE:
4988 break;
4989
4990 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004991 context->handleError(InvalidEnum() << "invalid hint mode.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004992 return false;
4993 }
4994
4995 switch (target)
4996 {
4997 case GL_GENERATE_MIPMAP_HINT:
4998 break;
4999
5000 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
5001 if (!context->getExtensions().standardDerivatives)
5002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005003 context->handleError(InvalidOperation()
5004 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005005 return false;
5006 }
5007 break;
5008
5009 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005010 context->handleError(InvalidEnum() << "invalid hint target.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005011 return false;
5012 }
5013
5014 return true;
5015}
5016
5017bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5018{
5019 return true;
5020}
5021
5022bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5023{
5024 return true;
5025}
5026
5027bool ValidateIsProgram(ValidationContext *context, GLuint program)
5028{
5029 return true;
5030}
5031
5032bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5033{
5034 return true;
5035}
5036
5037bool ValidateIsShader(ValidationContext *context, GLuint shader)
5038{
5039 return true;
5040}
5041
5042bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5043{
5044 return true;
5045}
5046
5047bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5048{
5049 if (context->getClientMajorVersion() < 3)
5050 {
5051 switch (pname)
5052 {
5053 case GL_UNPACK_IMAGE_HEIGHT:
5054 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005055 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005056 return false;
5057
5058 case GL_UNPACK_ROW_LENGTH:
5059 case GL_UNPACK_SKIP_ROWS:
5060 case GL_UNPACK_SKIP_PIXELS:
5061 if (!context->getExtensions().unpackSubimage)
5062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005063 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005064 return false;
5065 }
5066 break;
5067
5068 case GL_PACK_ROW_LENGTH:
5069 case GL_PACK_SKIP_ROWS:
5070 case GL_PACK_SKIP_PIXELS:
5071 if (!context->getExtensions().packSubimage)
5072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005073 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005074 return false;
5075 }
5076 break;
5077 }
5078 }
5079
5080 if (param < 0)
5081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005082 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005083 return false;
5084 }
5085
5086 switch (pname)
5087 {
5088 case GL_UNPACK_ALIGNMENT:
5089 if (param != 1 && param != 2 && param != 4 && param != 8)
5090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005091 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005092 return false;
5093 }
5094 break;
5095
5096 case GL_PACK_ALIGNMENT:
5097 if (param != 1 && param != 2 && param != 4 && param != 8)
5098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005099 context->handleError(InvalidValue());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005100 return false;
5101 }
5102 break;
5103
5104 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5105 case GL_UNPACK_ROW_LENGTH:
5106 case GL_UNPACK_IMAGE_HEIGHT:
5107 case GL_UNPACK_SKIP_IMAGES:
5108 case GL_UNPACK_SKIP_ROWS:
5109 case GL_UNPACK_SKIP_PIXELS:
5110 case GL_PACK_ROW_LENGTH:
5111 case GL_PACK_SKIP_ROWS:
5112 case GL_PACK_SKIP_PIXELS:
5113 break;
5114
5115 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005116 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005117 return false;
5118 }
5119
5120 return true;
5121}
5122
5123bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5124{
5125 return true;
5126}
5127
5128bool ValidateReleaseShaderCompiler(ValidationContext *context)
5129{
5130 return true;
5131}
5132
Jamie Madill876429b2017-04-20 15:46:24 -04005133bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005134{
5135 return true;
5136}
5137
5138bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5139{
5140 if (width < 0 || height < 0)
5141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005142 context->handleError(InvalidValue() << "Scissor width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005143 return false;
5144 }
5145
5146 return true;
5147}
5148
5149bool ValidateShaderBinary(ValidationContext *context,
5150 GLsizei n,
5151 const GLuint *shaders,
5152 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005153 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005154 GLsizei length)
5155{
5156 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5157 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5158 shaderBinaryFormats.end())
5159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005160 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005161 return false;
5162 }
5163
5164 return true;
5165}
5166
5167bool ValidateShaderSource(ValidationContext *context,
5168 GLuint shader,
5169 GLsizei count,
5170 const GLchar *const *string,
5171 const GLint *length)
5172{
5173 if (count < 0)
5174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005175 context->handleError(InvalidValue() << "Count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005176 return false;
5177 }
5178
Geoff Langfc32e8b2017-05-31 14:16:59 -04005179 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5180 // shader-related entry points
5181 if (context->getExtensions().webglCompatibility)
5182 {
5183 for (GLsizei i = 0; i < count; i++)
5184 {
5185 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
5186 if (!IsValidESSLString(string[i], len))
5187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005188 context->handleError(InvalidValue() << "Shader source contains invalid characters");
Geoff Langfc32e8b2017-05-31 14:16:59 -04005189 return false;
5190 }
5191 }
5192 }
5193
Jamie Madillc1d770e2017-04-13 17:31:24 -04005194 Shader *shaderObject = GetValidShader(context, shader);
5195 if (!shaderObject)
5196 {
5197 return false;
5198 }
5199
5200 return true;
5201}
5202
5203bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5204{
5205 if (!IsValidStencilFunc(func))
5206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005207 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005208 return false;
5209 }
5210
5211 return true;
5212}
5213
5214bool ValidateStencilFuncSeparate(ValidationContext *context,
5215 GLenum face,
5216 GLenum func,
5217 GLint ref,
5218 GLuint mask)
5219{
5220 if (!IsValidStencilFace(face))
5221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005222 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005223 return false;
5224 }
5225
5226 if (!IsValidStencilFunc(func))
5227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005228 context->handleError(InvalidEnum() << "Invalid stencil function.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005229 return false;
5230 }
5231
5232 return true;
5233}
5234
5235bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5236{
5237 return true;
5238}
5239
5240bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5241{
5242 if (!IsValidStencilFace(face))
5243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005244 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005245 return false;
5246 }
5247
5248 return true;
5249}
5250
5251bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5252{
5253 if (!IsValidStencilOp(fail))
5254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005255 context->handleError(InvalidEnum() << "Invalid stencil fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005256 return false;
5257 }
5258
5259 if (!IsValidStencilOp(zfail))
5260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005261 context->handleError(InvalidEnum() << "Invalid stencil z fail op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005262 return false;
5263 }
5264
5265 if (!IsValidStencilOp(zpass))
5266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005267 context->handleError(InvalidEnum() << "Invalid stencil z pass op.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005268 return false;
5269 }
5270
5271 return true;
5272}
5273
5274bool ValidateStencilOpSeparate(ValidationContext *context,
5275 GLenum face,
5276 GLenum fail,
5277 GLenum zfail,
5278 GLenum zpass)
5279{
5280 if (!IsValidStencilFace(face))
5281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005282 context->handleError(InvalidEnum() << "Invalid stencil face.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005283 return false;
5284 }
5285
5286 return ValidateStencilOp(context, fail, zfail, zpass);
5287}
5288
5289bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5290{
5291 return ValidateUniform(context, GL_FLOAT, location, 1);
5292}
5293
5294bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5295{
5296 return ValidateUniform(context, GL_FLOAT, location, count);
5297}
5298
Jamie Madillbe849e42017-05-02 15:49:00 -04005299bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5300{
5301 return ValidateUniform1iv(context, location, 1, &x);
5302}
5303
Jamie Madillc1d770e2017-04-13 17:31:24 -04005304bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5305{
5306 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5307}
5308
5309bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5310{
5311 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5312}
5313
5314bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5315{
5316 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5317}
5318
5319bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5320{
5321 return ValidateUniform(context, GL_INT_VEC2, location, count);
5322}
5323
5324bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5325{
5326 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5327}
5328
5329bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5330{
5331 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5332}
5333
5334bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5335{
5336 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5337}
5338
5339bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5340{
5341 return ValidateUniform(context, GL_INT_VEC3, location, count);
5342}
5343
5344bool ValidateUniform4f(ValidationContext *context,
5345 GLint location,
5346 GLfloat x,
5347 GLfloat y,
5348 GLfloat z,
5349 GLfloat w)
5350{
5351 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5352}
5353
5354bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5355{
5356 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5357}
5358
5359bool ValidateUniform4i(ValidationContext *context,
5360 GLint location,
5361 GLint x,
5362 GLint y,
5363 GLint z,
5364 GLint w)
5365{
5366 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5367}
5368
5369bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5370{
5371 return ValidateUniform(context, GL_INT_VEC4, location, count);
5372}
5373
5374bool ValidateUniformMatrix2fv(ValidationContext *context,
5375 GLint location,
5376 GLsizei count,
5377 GLboolean transpose,
5378 const GLfloat *value)
5379{
5380 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5381}
5382
5383bool ValidateUniformMatrix3fv(ValidationContext *context,
5384 GLint location,
5385 GLsizei count,
5386 GLboolean transpose,
5387 const GLfloat *value)
5388{
5389 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5390}
5391
5392bool ValidateUniformMatrix4fv(ValidationContext *context,
5393 GLint location,
5394 GLsizei count,
5395 GLboolean transpose,
5396 const GLfloat *value)
5397{
5398 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5399}
5400
5401bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5402{
5403 Program *programObject = GetValidProgram(context, program);
5404
5405 if (!programObject)
5406 {
5407 return false;
5408 }
5409
5410 return true;
5411}
5412
5413bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5414{
5415 if (index >= MAX_VERTEX_ATTRIBS)
5416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005417 context->handleError(InvalidValue() << "Vertex attrib index out of range.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005418 return false;
5419 }
5420
5421 return true;
5422}
5423
5424bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5425{
5426 return ValidateVertexAttribIndex(context, index);
5427}
5428
5429bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5430{
5431 return ValidateVertexAttribIndex(context, index);
5432}
5433
5434bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5435{
5436 return ValidateVertexAttribIndex(context, index);
5437}
5438
5439bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5440{
5441 return ValidateVertexAttribIndex(context, index);
5442}
5443
5444bool ValidateVertexAttrib3f(ValidationContext *context,
5445 GLuint index,
5446 GLfloat x,
5447 GLfloat y,
5448 GLfloat z)
5449{
5450 return ValidateVertexAttribIndex(context, index);
5451}
5452
5453bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5454{
5455 return ValidateVertexAttribIndex(context, index);
5456}
5457
5458bool ValidateVertexAttrib4f(ValidationContext *context,
5459 GLuint index,
5460 GLfloat x,
5461 GLfloat y,
5462 GLfloat z,
5463 GLfloat w)
5464{
5465 return ValidateVertexAttribIndex(context, index);
5466}
5467
5468bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5469{
5470 return ValidateVertexAttribIndex(context, index);
5471}
5472
5473bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5474{
5475 if (width < 0 || height < 0)
5476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005477 context->handleError(InvalidValue() << "Viewport width and height must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005478 return false;
5479 }
5480
5481 return true;
5482}
5483
5484bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5485{
5486 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5487}
5488
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005489bool ValidateDrawElements(ValidationContext *context,
5490 GLenum mode,
5491 GLsizei count,
5492 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005493 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005494{
5495 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5496}
5497
Jamie Madillbe849e42017-05-02 15:49:00 -04005498bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5499 GLenum target,
5500 GLenum attachment,
5501 GLenum pname,
5502 GLint *params)
5503{
5504 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5505 nullptr);
5506}
5507
5508bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5509{
5510 return ValidateGetProgramivBase(context, program, pname, nullptr);
5511}
5512
5513bool ValidateCopyTexImage2D(ValidationContext *context,
5514 GLenum target,
5515 GLint level,
5516 GLenum internalformat,
5517 GLint x,
5518 GLint y,
5519 GLsizei width,
5520 GLsizei height,
5521 GLint border)
5522{
5523 if (context->getClientMajorVersion() < 3)
5524 {
5525 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5526 0, x, y, width, height, border);
5527 }
5528
5529 ASSERT(context->getClientMajorVersion() == 3);
5530 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5531 0, x, y, width, height, border);
5532}
5533
5534bool ValidateCopyTexSubImage2D(Context *context,
5535 GLenum target,
5536 GLint level,
5537 GLint xoffset,
5538 GLint yoffset,
5539 GLint x,
5540 GLint y,
5541 GLsizei width,
5542 GLsizei height)
5543{
5544 if (context->getClientMajorVersion() < 3)
5545 {
5546 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5547 yoffset, x, y, width, height, 0);
5548 }
5549
5550 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5551 yoffset, 0, x, y, width, height, 0);
5552}
5553
5554bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5555{
5556 return ValidateGenOrDelete(context, n);
5557}
5558
5559bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5560{
5561 return ValidateGenOrDelete(context, n);
5562}
5563
5564bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5565{
5566 return ValidateGenOrDelete(context, n);
5567}
5568
5569bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5570{
5571 return ValidateGenOrDelete(context, n);
5572}
5573
5574bool ValidateDisable(Context *context, GLenum cap)
5575{
5576 if (!ValidCap(context, cap, false))
5577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005578 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005579 return false;
5580 }
5581
5582 return true;
5583}
5584
5585bool ValidateEnable(Context *context, GLenum cap)
5586{
5587 if (!ValidCap(context, cap, false))
5588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005589 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 return false;
5591 }
5592
5593 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5594 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5595 {
5596 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005597 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005598
5599 // We also output an error message to the debugger window if tracing is active, so that
5600 // developers can see the error message.
5601 ERR() << errorMessage;
5602 return false;
5603 }
5604
5605 return true;
5606}
5607
5608bool ValidateFramebufferRenderbuffer(Context *context,
5609 GLenum target,
5610 GLenum attachment,
5611 GLenum renderbuffertarget,
5612 GLuint renderbuffer)
5613{
5614 if (!ValidFramebufferTarget(target) ||
5615 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005617 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 return false;
5619 }
5620
5621 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5622 renderbuffertarget, renderbuffer);
5623}
5624
5625bool ValidateFramebufferTexture2D(Context *context,
5626 GLenum target,
5627 GLenum attachment,
5628 GLenum textarget,
5629 GLuint texture,
5630 GLint level)
5631{
5632 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5633 // extension
5634 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5635 level != 0)
5636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005637 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005638 return false;
5639 }
5640
5641 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5642 {
5643 return false;
5644 }
5645
5646 if (texture != 0)
5647 {
5648 gl::Texture *tex = context->getTexture(texture);
5649 ASSERT(tex);
5650
5651 const gl::Caps &caps = context->getCaps();
5652
5653 switch (textarget)
5654 {
5655 case GL_TEXTURE_2D:
5656 {
5657 if (level > gl::log2(caps.max2DTextureSize))
5658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005659 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 return false;
5661 }
5662 if (tex->getTarget() != GL_TEXTURE_2D)
5663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005664 context->handleError(InvalidOperation()
5665 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005666 return false;
5667 }
5668 }
5669 break;
5670
5671 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5672 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5673 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5674 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5675 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5676 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5677 {
5678 if (level > gl::log2(caps.maxCubeMapTextureSize))
5679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005680 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005681 return false;
5682 }
5683 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005685 context->handleError(InvalidOperation()
5686 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005687 return false;
5688 }
5689 }
5690 break;
5691
5692 case GL_TEXTURE_2D_MULTISAMPLE:
5693 {
5694 if (context->getClientVersion() < ES_3_1)
5695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005696 context->handleError(InvalidOperation()
5697 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005698 return false;
5699 }
5700
5701 if (level != 0)
5702 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005703 context->handleError(InvalidValue()
5704 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005705 return false;
5706 }
5707 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005709 context->handleError(InvalidOperation()
5710 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005711 return false;
5712 }
5713 }
5714 break;
5715
5716 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005717 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720
5721 const Format &format = tex->getFormat(textarget, level);
5722 if (format.info->compressed)
5723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005724 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005725 return false;
5726 }
5727 }
5728
5729 return true;
5730}
5731
5732bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5733{
5734 return ValidateGenOrDelete(context, n);
5735}
5736
5737bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5738{
5739 return ValidateGenOrDelete(context, n);
5740}
5741
5742bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5743{
5744 return ValidateGenOrDelete(context, n);
5745}
5746
5747bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5748{
5749 return ValidateGenOrDelete(context, n);
5750}
5751
5752bool ValidateGenerateMipmap(Context *context, GLenum target)
5753{
5754 if (!ValidTextureTarget(context, target))
5755 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005756 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -04005757 return false;
5758 }
5759
5760 Texture *texture = context->getTargetTexture(target);
5761
5762 if (texture == nullptr)
5763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005764 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 return false;
5766 }
5767
5768 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5769
5770 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5771 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5772 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005774 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005775 return false;
5776 }
5777
5778 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5779 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5780 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5781
5782 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5783 // unsized formats or that are color renderable and filterable. Since we do not track if
5784 // the texture was created with sized or unsized format (only sized formats are stored),
5785 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5786 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5787 // textures since they're the only texture format that can be created with unsized formats
5788 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5789 // was the last version to use add them.
5790 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5791 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005793 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 return false;
5795 }
5796
Geoff Lang65ac5b92017-05-01 13:16:30 -04005797 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5798 bool supportsSRGBMipmapGeneration =
5799 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5800 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005802 context->handleError(InvalidOperation()
5803 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
5806
5807 // Non-power of 2 ES2 check
5808 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5809 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5810 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5811 {
5812 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005813 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005814 return false;
5815 }
5816
5817 // Cube completeness check
5818 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005820 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 return false;
5822 }
5823
5824 return true;
5825}
5826
5827bool ValidateGetBufferParameteriv(ValidationContext *context,
5828 GLenum target,
5829 GLenum pname,
5830 GLint *params)
5831{
5832 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5833}
5834
5835bool ValidateGetRenderbufferParameteriv(Context *context,
5836 GLenum target,
5837 GLenum pname,
5838 GLint *params)
5839{
5840 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5841}
5842
5843bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5844{
5845 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5846}
5847
5848bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5849{
5850 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5851}
5852
5853bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5854{
5855 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5856}
5857
5858bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5859{
5860 return ValidateGetUniformBase(context, program, location);
5861}
5862
5863bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5864{
5865 return ValidateGetUniformBase(context, program, location);
5866}
5867
5868bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5869{
5870 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5871}
5872
5873bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5874{
5875 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5876}
5877
5878bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5879{
5880 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5881}
5882
5883bool ValidateIsEnabled(Context *context, GLenum cap)
5884{
5885 if (!ValidCap(context, cap, true))
5886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005887 context->handleError(InvalidEnum() << "Invalid cap.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 return false;
5889 }
5890
5891 return true;
5892}
5893
5894bool ValidateLinkProgram(Context *context, GLuint program)
5895{
5896 if (context->hasActiveTransformFeedback(program))
5897 {
5898 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005899 context->handleError(InvalidOperation() << "Cannot link program while program is "
5900 "associated with an active transform "
5901 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005902 return false;
5903 }
5904
5905 Program *programObject = GetValidProgram(context, program);
5906 if (!programObject)
5907 {
5908 return false;
5909 }
5910
5911 return true;
5912}
5913
5914bool ValidateReadPixels(ValidationContext *context,
5915 GLint x,
5916 GLint y,
5917 GLsizei width,
5918 GLsizei height,
5919 GLenum format,
5920 GLenum type,
5921 void *pixels)
5922{
5923 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5924 nullptr, pixels);
5925}
5926
5927bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5928{
5929 return ValidateTexParameterBase(context, target, pname, -1, &param);
5930}
5931
5932bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5933{
5934 return ValidateTexParameterBase(context, target, pname, -1, params);
5935}
5936
5937bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5938{
5939 return ValidateTexParameterBase(context, target, pname, -1, &param);
5940}
5941
5942bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5943{
5944 return ValidateTexParameterBase(context, target, pname, -1, params);
5945}
5946
5947bool ValidateUseProgram(Context *context, GLuint program)
5948{
5949 if (program != 0)
5950 {
5951 Program *programObject = context->getProgram(program);
5952 if (!programObject)
5953 {
5954 // ES 3.1.0 section 7.3 page 72
5955 if (context->getShader(program))
5956 {
5957 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005958 InvalidOperation()
5959 << "Attempted to use a single shader instead of a shader program.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005960 return false;
5961 }
5962 else
5963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005964 context->handleError(InvalidValue() << "Program invalid.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005965 return false;
5966 }
5967 }
5968 if (!programObject->isLinked())
5969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005970 context->handleError(InvalidOperation() << "Program not linked.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005971 return false;
5972 }
5973 }
5974 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5975 {
5976 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005977 context
5978 ->handleError(InvalidOperation()
5979 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005980 return false;
5981 }
5982
5983 return true;
5984}
5985
Jamie Madillc29968b2016-01-20 11:17:23 -05005986} // namespace gl