blob: 8ec453d3610bd022d296a120966de387cd6231ed [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 {
78 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
79 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 {
95 context->handleError(
96 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
97 return false;
98 }
99
100 if (paths == nullptr)
101 {
102 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
103 return false;
104 }
105
106 if (numPaths < 0)
107 {
108 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
114 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
160 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
188 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
193 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
202 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang4f0e0032017-05-01 16:04:35 -0400209bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
Geoff Lang97073d12016-04-20 10:42:34 -0700210{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400211 // Table 1.1 from the CHROMIUM_copy_texture spec
Geoff Langca271392017-04-05 12:30:00 -0400212 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700213 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400214 case GL_RED:
Geoff Lang97073d12016-04-20 10:42:34 -0700215 case GL_ALPHA:
216 case GL_LUMINANCE:
217 case GL_LUMINANCE_ALPHA:
218 case GL_RGB:
219 case GL_RGBA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400220 case GL_RGB8:
221 case GL_RGBA8:
222 case GL_BGRA_EXT:
223 case GL_BGRA8_EXT:
Geoff Lang97073d12016-04-20 10:42:34 -0700224 return true;
225
Geoff Lang4f0e0032017-05-01 16:04:35 -0400226 default:
227 return false;
228 }
229}
Geoff Lang97073d12016-04-20 10:42:34 -0700230
Geoff Lang4f0e0032017-05-01 16:04:35 -0400231bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
232{
233 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
234}
235
236bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
237{
238 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
239}
240
241bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
242{
243 // Table 1.0 from the CHROMIUM_copy_texture spec
244 switch (internalFormat)
245 {
246 case GL_RGB:
247 case GL_RGBA:
248 case GL_RGB8:
249 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700250 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400251 case GL_BGRA8_EXT:
252 case GL_SRGB_EXT:
253 case GL_SRGB_ALPHA_EXT:
254 case GL_R8:
255 case GL_R8UI:
256 case GL_RG8:
257 case GL_RG8UI:
258 case GL_SRGB8:
259 case GL_RGB565:
260 case GL_RGB8UI:
261 case GL_SRGB8_ALPHA8:
262 case GL_RGB5_A1:
263 case GL_RGBA4:
264 case GL_RGBA8UI:
265 case GL_RGB9_E5:
266 case GL_R16F:
267 case GL_R32F:
268 case GL_RG16F:
269 case GL_RG32F:
270 case GL_RGB16F:
271 case GL_RGB32F:
272 case GL_RGBA16F:
273 case GL_RGBA32F:
274 case GL_R11F_G11F_B10F:
275 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700276
277 default:
278 return false;
279 }
280}
281
282bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
283{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400284 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700285 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400286 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700287 }
288
Geoff Lang4f0e0032017-05-01 16:04:35 -0400289 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
290 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700291 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400292 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700293 }
294
295 return true;
296}
297
Geoff Lang4f0e0032017-05-01 16:04:35 -0400298bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700299{
300 switch (target)
301 {
302 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400303 return textureType == GL_TEXTURE_2D;
304
305 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
306 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
307 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
308 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
309 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
310 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
311 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700312
313 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
314 // supported
315
316 default:
317 return false;
318 }
319}
320
321bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
322{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400323 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700324 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400325 case GL_TEXTURE_2D:
326 return true;
327
328 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
329 // supported
330
331 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
332 // supported
333
334 default:
335 return false;
336 }
337}
338
339bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
340{
341 if (level < 0)
342 {
343 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700344 }
345
Geoff Lang4f0e0032017-05-01 16:04:35 -0400346 if (level > 0 && context->getClientVersion() < ES_3_0)
347 {
348 return false;
349 }
Geoff Lang97073d12016-04-20 10:42:34 -0700350
Geoff Lang4f0e0032017-05-01 16:04:35 -0400351 return true;
352}
353
354bool IsValidCopyTextureDestinationLevel(Context *context,
355 GLenum target,
356 GLint level,
357 GLsizei width,
358 GLsizei height)
359{
360 if (level < 0)
361 {
362 return false;
363 }
364
365 if (level > 0 && context->getClientVersion() < ES_3_0)
366 {
367 return false;
368 }
369
370 const Caps &caps = context->getCaps();
371 if (target == GL_TEXTURE_2D)
372 {
373 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
374 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
375 {
376 return false;
377 }
378 }
379 else if (IsCubeMapTextureTarget(target))
380 {
381 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
382 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
383 {
384 return false;
385 }
386 }
387
388 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700389}
390
Jamie Madillc1d770e2017-04-13 17:31:24 -0400391bool IsValidStencilFunc(GLenum func)
392{
393 switch (func)
394 {
395 case GL_NEVER:
396 case GL_ALWAYS:
397 case GL_LESS:
398 case GL_LEQUAL:
399 case GL_EQUAL:
400 case GL_GEQUAL:
401 case GL_GREATER:
402 case GL_NOTEQUAL:
403 return true;
404
405 default:
406 return false;
407 }
408}
409
410bool IsValidStencilFace(GLenum face)
411{
412 switch (face)
413 {
414 case GL_FRONT:
415 case GL_BACK:
416 case GL_FRONT_AND_BACK:
417 return true;
418
419 default:
420 return false;
421 }
422}
423
424bool IsValidStencilOp(GLenum op)
425{
426 switch (op)
427 {
428 case GL_ZERO:
429 case GL_KEEP:
430 case GL_REPLACE:
431 case GL_INCR:
432 case GL_DECR:
433 case GL_INVERT:
434 case GL_INCR_WRAP:
435 case GL_DECR_WRAP:
436 return true;
437
438 default:
439 return false;
440 }
441}
442
Jamie Madillbe849e42017-05-02 15:49:00 -0400443bool ValidateES2CopyTexImageParameters(ValidationContext *context,
444 GLenum target,
445 GLint level,
446 GLenum internalformat,
447 bool isSubImage,
448 GLint xoffset,
449 GLint yoffset,
450 GLint x,
451 GLint y,
452 GLsizei width,
453 GLsizei height,
454 GLint border)
455{
456 if (!ValidTexture2DDestinationTarget(context, target))
457 {
458 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
459 return false;
460 }
461
462 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
463 {
464 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
465 return false;
466 }
467
468 Format textureFormat = Format::Invalid();
469 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
470 xoffset, yoffset, 0, x, y, width, height, border,
471 &textureFormat))
472 {
473 return false;
474 }
475
476 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
477 GLenum colorbufferFormat =
478 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
479 const auto &formatInfo = *textureFormat.info;
480
481 // [OpenGL ES 2.0.24] table 3.9
482 if (isSubImage)
483 {
484 switch (formatInfo.format)
485 {
486 case GL_ALPHA:
487 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400488 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
489 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400490 {
491 context->handleError(Error(GL_INVALID_OPERATION));
492 return false;
493 }
494 break;
495 case GL_LUMINANCE:
496 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
497 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
498 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400499 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
500 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400501 {
502 context->handleError(Error(GL_INVALID_OPERATION));
503 return false;
504 }
505 break;
506 case GL_RED_EXT:
507 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
508 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
509 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
510 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
511 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400512 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
513 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400514 {
515 context->handleError(Error(GL_INVALID_OPERATION));
516 return false;
517 }
518 break;
519 case GL_RG_EXT:
520 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
521 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
522 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
523 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400524 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
525 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400526 {
527 context->handleError(Error(GL_INVALID_OPERATION));
528 return false;
529 }
530 break;
531 case GL_RGB:
532 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
533 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
534 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400535 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
536 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400537 {
538 context->handleError(Error(GL_INVALID_OPERATION));
539 return false;
540 }
541 break;
542 case GL_LUMINANCE_ALPHA:
543 case GL_RGBA:
544 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400545 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
546 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400547 {
548 context->handleError(Error(GL_INVALID_OPERATION));
549 return false;
550 }
551 break;
552 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
553 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
554 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
555 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
556 case GL_ETC1_RGB8_OES:
557 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
558 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
559 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
560 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
561 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
562 context->handleError(Error(GL_INVALID_OPERATION));
563 return false;
564 case GL_DEPTH_COMPONENT:
565 case GL_DEPTH_STENCIL_OES:
566 context->handleError(Error(GL_INVALID_OPERATION));
567 return false;
568 default:
569 context->handleError(Error(GL_INVALID_OPERATION));
570 return false;
571 }
572
573 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
574 {
575 context->handleError(Error(GL_INVALID_OPERATION));
576 return false;
577 }
578 }
579 else
580 {
581 switch (internalformat)
582 {
583 case GL_ALPHA:
584 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
585 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
586 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
587 {
588 context->handleError(Error(GL_INVALID_OPERATION));
589 return false;
590 }
591 break;
592 case GL_LUMINANCE:
593 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
594 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
595 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
596 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
597 colorbufferFormat != GL_BGR5_A1_ANGLEX)
598 {
599 context->handleError(Error(GL_INVALID_OPERATION));
600 return false;
601 }
602 break;
603 case GL_RED_EXT:
604 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
605 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
606 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
607 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
608 colorbufferFormat != GL_BGR5_A1_ANGLEX)
609 {
610 context->handleError(Error(GL_INVALID_OPERATION));
611 return false;
612 }
613 break;
614 case GL_RG_EXT:
615 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
616 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
617 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
618 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
619 {
620 context->handleError(Error(GL_INVALID_OPERATION));
621 return false;
622 }
623 break;
624 case GL_RGB:
625 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
626 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
627 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
628 colorbufferFormat != GL_BGR5_A1_ANGLEX)
629 {
630 context->handleError(Error(GL_INVALID_OPERATION));
631 return false;
632 }
633 break;
634 case GL_LUMINANCE_ALPHA:
635 case GL_RGBA:
636 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
637 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
638 colorbufferFormat != GL_BGR5_A1_ANGLEX)
639 {
640 context->handleError(Error(GL_INVALID_OPERATION));
641 return false;
642 }
643 break;
644 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
645 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
646 if (context->getExtensions().textureCompressionDXT1)
647 {
648 context->handleError(Error(GL_INVALID_OPERATION));
649 return false;
650 }
651 else
652 {
653 context->handleError(Error(GL_INVALID_ENUM));
654 return false;
655 }
656 break;
657 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
658 if (context->getExtensions().textureCompressionDXT3)
659 {
660 context->handleError(Error(GL_INVALID_OPERATION));
661 return false;
662 }
663 else
664 {
665 context->handleError(Error(GL_INVALID_ENUM));
666 return false;
667 }
668 break;
669 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
670 if (context->getExtensions().textureCompressionDXT5)
671 {
672 context->handleError(Error(GL_INVALID_OPERATION));
673 return false;
674 }
675 else
676 {
677 context->handleError(Error(GL_INVALID_ENUM));
678 return false;
679 }
680 break;
681 case GL_ETC1_RGB8_OES:
682 if (context->getExtensions().compressedETC1RGB8Texture)
683 {
684 context->handleError(Error(GL_INVALID_OPERATION));
685 return false;
686 }
687 else
688 {
689 context->handleError(Error(GL_INVALID_ENUM));
690 return false;
691 }
692 break;
693 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
694 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
695 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
696 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
697 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
698 if (context->getExtensions().lossyETCDecode)
699 {
700 context->handleError(Error(GL_INVALID_OPERATION,
701 "ETC lossy decode formats can't be copied to."));
702 return false;
703 }
704 else
705 {
706 context->handleError(Error(
707 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
708 return false;
709 }
710 break;
711 case GL_DEPTH_COMPONENT:
712 case GL_DEPTH_COMPONENT16:
713 case GL_DEPTH_COMPONENT32_OES:
714 case GL_DEPTH_STENCIL_OES:
715 case GL_DEPTH24_STENCIL8_OES:
716 if (context->getExtensions().depthTextures)
717 {
718 context->handleError(Error(GL_INVALID_OPERATION));
719 return false;
720 }
721 else
722 {
723 context->handleError(Error(GL_INVALID_ENUM));
724 return false;
725 }
726 default:
727 context->handleError(Error(GL_INVALID_ENUM));
728 return false;
729 }
730 }
731
732 // If width or height is zero, it is a no-op. Return false without setting an error.
733 return (width > 0 && height > 0);
734}
735
736bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
737{
738 switch (cap)
739 {
740 // EXT_multisample_compatibility
741 case GL_MULTISAMPLE_EXT:
742 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
743 return context->getExtensions().multisampleCompatibility;
744
745 case GL_CULL_FACE:
746 case GL_POLYGON_OFFSET_FILL:
747 case GL_SAMPLE_ALPHA_TO_COVERAGE:
748 case GL_SAMPLE_COVERAGE:
749 case GL_SCISSOR_TEST:
750 case GL_STENCIL_TEST:
751 case GL_DEPTH_TEST:
752 case GL_BLEND:
753 case GL_DITHER:
754 return true;
755
756 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
757 case GL_RASTERIZER_DISCARD:
758 return (context->getClientMajorVersion() >= 3);
759
760 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
761 case GL_DEBUG_OUTPUT:
762 return context->getExtensions().debug;
763
764 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
765 return queryOnly && context->getExtensions().bindGeneratesResource;
766
767 case GL_CLIENT_ARRAYS_ANGLE:
768 return queryOnly && context->getExtensions().clientArrays;
769
770 case GL_FRAMEBUFFER_SRGB_EXT:
771 return context->getExtensions().sRGBWriteControl;
772
773 case GL_SAMPLE_MASK:
774 return context->getClientVersion() >= Version(3, 1);
775
776 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
777 return queryOnly && context->getExtensions().robustResourceInitialization;
778
779 default:
780 return false;
781 }
782}
783
Geoff Langfc32e8b2017-05-31 14:16:59 -0400784// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
785// 3.1.
786bool IsValidESSLCharacter(unsigned char c)
787{
788 // Printing characters are valid except " $ ` @ \ ' DEL.
789 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
790 c != '\'')
791 {
792 return true;
793 }
794
795 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
796 if (c >= 9 && c <= 13)
797 {
798 return true;
799 }
800
801 return false;
802}
803
804bool IsValidESSLString(const char *str, size_t len)
805{
806 return len == 0 || std::find_if_not(str, str + len, IsValidESSLCharacter) == str + len;
807}
808
Jamie Madillc29968b2016-01-20 11:17:23 -0500809} // anonymous namespace
810
Geoff Langff5b2d52016-09-07 11:32:23 -0400811bool ValidateES2TexImageParameters(Context *context,
812 GLenum target,
813 GLint level,
814 GLenum internalformat,
815 bool isCompressed,
816 bool isSubImage,
817 GLint xoffset,
818 GLint yoffset,
819 GLsizei width,
820 GLsizei height,
821 GLint border,
822 GLenum format,
823 GLenum type,
824 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400825 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826{
Jamie Madill6f38f822014-06-06 17:12:20 -0400827 if (!ValidTexture2DDestinationTarget(context, target))
828 {
Jamie Madill437fa652016-05-03 15:13:24 -0400829 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400830 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400831 }
832
Austin Kinross08528e12015-10-07 16:24:40 -0700833 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 {
Jamie Madill437fa652016-05-03 15:13:24 -0400835 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400836 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 }
838
He Yunchaoced53ae2016-11-29 15:00:51 +0800839 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400840 std::numeric_limits<GLsizei>::max() - yoffset < height)
841 {
Jamie Madill437fa652016-05-03 15:13:24 -0400842 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 }
845
Geoff Lang005df412013-10-16 14:12:50 -0400846 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851
Geoff Langaae65a42014-05-26 12:43:44 -0400852 const gl::Caps &caps = context->getCaps();
853
Geoff Langa9be0dc2014-12-17 12:34:40 -0500854 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500856 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
857 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 {
Jamie Madill437fa652016-05-03 15:13:24 -0400859 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500860 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500862 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500863 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500864 {
865 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 {
Jamie Madill437fa652016-05-03 15:13:24 -0400867 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500868 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400870
Geoff Langa9be0dc2014-12-17 12:34:40 -0500871 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
872 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
873 {
Jamie Madill437fa652016-05-03 15:13:24 -0400874 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500875 return false;
876 }
877 }
878 else
879 {
Jamie Madill437fa652016-05-03 15:13:24 -0400880 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400881 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400882 }
883
He Yunchaoced53ae2016-11-29 15:00:51 +0800884 gl::Texture *texture =
885 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400886 if (!texture)
887 {
Jamie Madill437fa652016-05-03 15:13:24 -0400888 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400889 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400890 }
891
Geoff Langa9be0dc2014-12-17 12:34:40 -0500892 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 {
Geoff Langca271392017-04-05 12:30:00 -0400894 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
895 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500896 {
897 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
898 return false;
899 }
900
Geoff Langa9be0dc2014-12-17 12:34:40 -0500901 if (format != GL_NONE)
902 {
Geoff Langca271392017-04-05 12:30:00 -0400903 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
904 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500905 {
Jamie Madill437fa652016-05-03 15:13:24 -0400906 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500907 return false;
908 }
909 }
910
911 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
912 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
913 {
Jamie Madill437fa652016-05-03 15:13:24 -0400914 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500915 return false;
916 }
917 }
918 else
919 {
Geoff Lang69cce582015-09-17 13:20:36 -0400920 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500921 {
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500923 return false;
924 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 }
926
927 // Verify zero border
928 if (border != 0)
929 {
Jamie Madill437fa652016-05-03 15:13:24 -0400930 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400931 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 }
933
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 if (isCompressed)
935 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400936 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400937 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
938 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939 switch (actualInternalFormat)
940 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800941 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
942 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
943 if (!context->getExtensions().textureCompressionDXT1)
944 {
945 context->handleError(Error(GL_INVALID_ENUM));
946 return false;
947 }
948 break;
949 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
950 if (!context->getExtensions().textureCompressionDXT1)
951 {
952 context->handleError(Error(GL_INVALID_ENUM));
953 return false;
954 }
955 break;
956 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
957 if (!context->getExtensions().textureCompressionDXT5)
958 {
959 context->handleError(Error(GL_INVALID_ENUM));
960 return false;
961 }
962 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800963 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
964 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
965 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
966 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
967 if (!context->getExtensions().textureCompressionS3TCsRGB)
968 {
969 context->handleError(Error(GL_INVALID_ENUM));
970 return false;
971 }
972 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800973 case GL_ETC1_RGB8_OES:
974 if (!context->getExtensions().compressedETC1RGB8Texture)
975 {
976 context->handleError(Error(GL_INVALID_ENUM));
977 return false;
978 }
979 break;
980 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800981 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
982 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
983 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
984 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 if (!context->getExtensions().lossyETCDecode)
986 {
987 context->handleError(Error(
988 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
989 return false;
990 }
991 break;
992 default:
993 context->handleError(
994 Error(GL_INVALID_ENUM,
995 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400996 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400997 }
Geoff Lang966c9402017-04-18 12:38:27 -0400998
999 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001000 {
Geoff Lang966c9402017-04-18 12:38:27 -04001001 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1002 height, texture->getWidth(target, level),
1003 texture->getHeight(target, level)))
1004 {
1005 context->handleError(
1006 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
1007 return false;
1008 }
1009
1010 if (format != actualInternalFormat)
1011 {
1012 context->handleError(Error(
1013 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
1014 return false;
1015 }
1016 }
1017 else
1018 {
1019 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1020 {
1021 context->handleError(
1022 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
1023 return false;
1024 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 }
1026 }
1027 else
1028 {
1029 // validate <type> by itself (used as secondary key below)
1030 switch (type)
1031 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001032 case GL_UNSIGNED_BYTE:
1033 case GL_UNSIGNED_SHORT_5_6_5:
1034 case GL_UNSIGNED_SHORT_4_4_4_4:
1035 case GL_UNSIGNED_SHORT_5_5_5_1:
1036 case GL_UNSIGNED_SHORT:
1037 case GL_UNSIGNED_INT:
1038 case GL_UNSIGNED_INT_24_8_OES:
1039 case GL_HALF_FLOAT_OES:
1040 case GL_FLOAT:
1041 break;
1042 default:
1043 context->handleError(Error(GL_INVALID_ENUM));
1044 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 }
1046
1047 // validate <format> + <type> combinations
1048 // - invalid <format> -> sets INVALID_ENUM
1049 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1050 switch (format)
1051 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001052 case GL_ALPHA:
1053 case GL_LUMINANCE:
1054 case GL_LUMINANCE_ALPHA:
1055 switch (type)
1056 {
1057 case GL_UNSIGNED_BYTE:
1058 case GL_FLOAT:
1059 case GL_HALF_FLOAT_OES:
1060 break;
1061 default:
1062 context->handleError(Error(GL_INVALID_OPERATION));
1063 return false;
1064 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001066 case GL_RED:
1067 case GL_RG:
1068 if (!context->getExtensions().textureRG)
1069 {
1070 context->handleError(Error(GL_INVALID_ENUM));
1071 return false;
1072 }
1073 switch (type)
1074 {
1075 case GL_UNSIGNED_BYTE:
1076 case GL_FLOAT:
1077 case GL_HALF_FLOAT_OES:
1078 break;
1079 default:
1080 context->handleError(Error(GL_INVALID_OPERATION));
1081 return false;
1082 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001084 case GL_RGB:
1085 switch (type)
1086 {
1087 case GL_UNSIGNED_BYTE:
1088 case GL_UNSIGNED_SHORT_5_6_5:
1089 case GL_FLOAT:
1090 case GL_HALF_FLOAT_OES:
1091 break;
1092 default:
1093 context->handleError(Error(GL_INVALID_OPERATION));
1094 return false;
1095 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001097 case GL_RGBA:
1098 switch (type)
1099 {
1100 case GL_UNSIGNED_BYTE:
1101 case GL_UNSIGNED_SHORT_4_4_4_4:
1102 case GL_UNSIGNED_SHORT_5_5_5_1:
1103 case GL_FLOAT:
1104 case GL_HALF_FLOAT_OES:
1105 break;
1106 default:
1107 context->handleError(Error(GL_INVALID_OPERATION));
1108 return false;
1109 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 case GL_BGRA_EXT:
1112 switch (type)
1113 {
1114 case GL_UNSIGNED_BYTE:
1115 break;
1116 default:
1117 context->handleError(Error(GL_INVALID_OPERATION));
1118 return false;
1119 }
1120 break;
1121 case GL_SRGB_EXT:
1122 case GL_SRGB_ALPHA_EXT:
1123 if (!context->getExtensions().sRGB)
1124 {
1125 context->handleError(Error(GL_INVALID_ENUM));
1126 return false;
1127 }
1128 switch (type)
1129 {
1130 case GL_UNSIGNED_BYTE:
1131 break;
1132 default:
1133 context->handleError(Error(GL_INVALID_OPERATION));
1134 return false;
1135 }
1136 break;
1137 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1138 // handled below
1139 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1140 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1141 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1142 break;
1143 case GL_DEPTH_COMPONENT:
1144 switch (type)
1145 {
1146 case GL_UNSIGNED_SHORT:
1147 case GL_UNSIGNED_INT:
1148 break;
1149 default:
1150 context->handleError(Error(GL_INVALID_OPERATION));
1151 return false;
1152 }
1153 break;
1154 case GL_DEPTH_STENCIL_OES:
1155 switch (type)
1156 {
1157 case GL_UNSIGNED_INT_24_8_OES:
1158 break;
1159 default:
1160 context->handleError(Error(GL_INVALID_OPERATION));
1161 return false;
1162 }
1163 break;
1164 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 }
1168
1169 switch (format)
1170 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001171 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1172 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1173 if (context->getExtensions().textureCompressionDXT1)
1174 {
1175 context->handleError(Error(GL_INVALID_OPERATION));
1176 return false;
1177 }
1178 else
1179 {
1180 context->handleError(Error(GL_INVALID_ENUM));
1181 return false;
1182 }
1183 break;
1184 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1185 if (context->getExtensions().textureCompressionDXT3)
1186 {
1187 context->handleError(Error(GL_INVALID_OPERATION));
1188 return false;
1189 }
1190 else
1191 {
1192 context->handleError(Error(GL_INVALID_ENUM));
1193 return false;
1194 }
1195 break;
1196 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1197 if (context->getExtensions().textureCompressionDXT5)
1198 {
1199 context->handleError(Error(GL_INVALID_OPERATION));
1200 return false;
1201 }
1202 else
1203 {
1204 context->handleError(Error(GL_INVALID_ENUM));
1205 return false;
1206 }
1207 break;
1208 case GL_ETC1_RGB8_OES:
1209 if (context->getExtensions().compressedETC1RGB8Texture)
1210 {
1211 context->handleError(Error(GL_INVALID_OPERATION));
1212 return false;
1213 }
1214 else
1215 {
1216 context->handleError(Error(GL_INVALID_ENUM));
1217 return false;
1218 }
1219 break;
1220 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001221 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1222 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1223 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1224 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 if (context->getExtensions().lossyETCDecode)
1226 {
1227 context->handleError(
1228 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -08001229 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +08001230 return false;
1231 }
1232 else
1233 {
1234 context->handleError(Error(
1235 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1236 return false;
1237 }
1238 break;
1239 case GL_DEPTH_COMPONENT:
1240 case GL_DEPTH_STENCIL_OES:
1241 if (!context->getExtensions().depthTextures)
1242 {
1243 context->handleError(Error(GL_INVALID_VALUE));
1244 return false;
1245 }
1246 if (target != GL_TEXTURE_2D)
1247 {
1248 context->handleError(Error(GL_INVALID_OPERATION));
1249 return false;
1250 }
1251 // OES_depth_texture supports loading depth data and multiple levels,
1252 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001253 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001254 {
1255 context->handleError(Error(GL_INVALID_OPERATION));
1256 return false;
1257 }
1258 break;
1259 default:
1260 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 }
1262
1263 if (type == GL_FLOAT)
1264 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001265 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001266 {
Jamie Madill437fa652016-05-03 15:13:24 -04001267 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001268 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 }
1270 }
1271 else if (type == GL_HALF_FLOAT_OES)
1272 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001273 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 {
Jamie Madill437fa652016-05-03 15:13:24 -04001275 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001276 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 }
1278 }
1279 }
1280
Geoff Langff5b2d52016-09-07 11:32:23 -04001281 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
1282 imageSize))
1283 {
1284 return false;
1285 }
1286
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 return true;
1288}
1289
He Yunchaoced53ae2016-11-29 15:00:51 +08001290bool ValidateES2TexStorageParameters(Context *context,
1291 GLenum target,
1292 GLsizei levels,
1293 GLenum internalformat,
1294 GLsizei width,
1295 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001296{
1297 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1298 {
Jamie Madill437fa652016-05-03 15:13:24 -04001299 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 }
1302
1303 if (width < 1 || height < 1 || levels < 1)
1304 {
Jamie Madill437fa652016-05-03 15:13:24 -04001305 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001306 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307 }
1308
1309 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1310 {
Jamie Madill437fa652016-05-03 15:13:24 -04001311 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001312 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313 }
1314
1315 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1316 {
Jamie Madill437fa652016-05-03 15:13:24 -04001317 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001318 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001319 }
1320
Geoff Langca271392017-04-05 12:30:00 -04001321 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001322 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Jamie Madill437fa652016-05-03 15:13:24 -04001324 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326 }
1327
Geoff Langaae65a42014-05-26 12:43:44 -04001328 const gl::Caps &caps = context->getCaps();
1329
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 switch (target)
1331 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001332 case GL_TEXTURE_2D:
1333 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1334 static_cast<GLuint>(height) > caps.max2DTextureSize)
1335 {
1336 context->handleError(Error(GL_INVALID_VALUE));
1337 return false;
1338 }
1339 break;
1340 case GL_TEXTURE_CUBE_MAP:
1341 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1342 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1343 {
1344 context->handleError(Error(GL_INVALID_VALUE));
1345 return false;
1346 }
1347 break;
1348 default:
1349 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 }
1352
Geoff Langc0b9ef42014-07-02 10:02:37 -04001353 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 {
1355 if (!gl::isPow2(width) || !gl::isPow2(height))
1356 {
Jamie Madill437fa652016-05-03 15:13:24 -04001357 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 }
1360 }
1361
1362 switch (internalformat)
1363 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001364 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1365 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1366 if (!context->getExtensions().textureCompressionDXT1)
1367 {
1368 context->handleError(Error(GL_INVALID_ENUM));
1369 return false;
1370 }
1371 break;
1372 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1373 if (!context->getExtensions().textureCompressionDXT3)
1374 {
1375 context->handleError(Error(GL_INVALID_ENUM));
1376 return false;
1377 }
1378 break;
1379 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1380 if (!context->getExtensions().textureCompressionDXT5)
1381 {
1382 context->handleError(Error(GL_INVALID_ENUM));
1383 return false;
1384 }
1385 break;
1386 case GL_ETC1_RGB8_OES:
1387 if (!context->getExtensions().compressedETC1RGB8Texture)
1388 {
1389 context->handleError(Error(GL_INVALID_ENUM));
1390 return false;
1391 }
1392 break;
1393 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001394 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1395 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1396 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1397 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001398 if (!context->getExtensions().lossyETCDecode)
1399 {
1400 context->handleError(
1401 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1402 return false;
1403 }
1404 break;
1405 case GL_RGBA32F_EXT:
1406 case GL_RGB32F_EXT:
1407 case GL_ALPHA32F_EXT:
1408 case GL_LUMINANCE32F_EXT:
1409 case GL_LUMINANCE_ALPHA32F_EXT:
1410 if (!context->getExtensions().textureFloat)
1411 {
1412 context->handleError(Error(GL_INVALID_ENUM));
1413 return false;
1414 }
1415 break;
1416 case GL_RGBA16F_EXT:
1417 case GL_RGB16F_EXT:
1418 case GL_ALPHA16F_EXT:
1419 case GL_LUMINANCE16F_EXT:
1420 case GL_LUMINANCE_ALPHA16F_EXT:
1421 if (!context->getExtensions().textureHalfFloat)
1422 {
1423 context->handleError(Error(GL_INVALID_ENUM));
1424 return false;
1425 }
1426 break;
1427 case GL_R8_EXT:
1428 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001429 if (!context->getExtensions().textureRG)
1430 {
1431 context->handleError(Error(GL_INVALID_ENUM));
1432 return false;
1433 }
1434 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001435 case GL_R16F_EXT:
1436 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001437 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1438 {
1439 context->handleError(Error(GL_INVALID_ENUM));
1440 return false;
1441 }
1442 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001443 case GL_R32F_EXT:
1444 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001445 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001446 {
1447 context->handleError(Error(GL_INVALID_ENUM));
1448 return false;
1449 }
1450 break;
1451 case GL_DEPTH_COMPONENT16:
1452 case GL_DEPTH_COMPONENT32_OES:
1453 case GL_DEPTH24_STENCIL8_OES:
1454 if (!context->getExtensions().depthTextures)
1455 {
1456 context->handleError(Error(GL_INVALID_ENUM));
1457 return false;
1458 }
1459 if (target != GL_TEXTURE_2D)
1460 {
1461 context->handleError(Error(GL_INVALID_OPERATION));
1462 return false;
1463 }
1464 // ANGLE_depth_texture only supports 1-level textures
1465 if (levels != 1)
1466 {
1467 context->handleError(Error(GL_INVALID_OPERATION));
1468 return false;
1469 }
1470 break;
1471 default:
1472 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 }
1474
Geoff Lang691e58c2014-12-19 17:03:25 -05001475 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001476 if (!texture || texture->id() == 0)
1477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001479 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 }
1481
Geoff Lang69cce582015-09-17 13:20:36 -04001482 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001483 {
Jamie Madill437fa652016-05-03 15:13:24 -04001484 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001485 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001486 }
1487
1488 return true;
1489}
1490
He Yunchaoced53ae2016-11-29 15:00:51 +08001491bool ValidateDiscardFramebufferEXT(Context *context,
1492 GLenum target,
1493 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001494 const GLenum *attachments)
1495{
Jamie Madillc29968b2016-01-20 11:17:23 -05001496 if (!context->getExtensions().discardFramebuffer)
1497 {
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001499 return false;
1500 }
1501
Austin Kinross08332632015-05-05 13:35:47 -07001502 bool defaultFramebuffer = false;
1503
1504 switch (target)
1505 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001506 case GL_FRAMEBUFFER:
1507 defaultFramebuffer =
1508 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1509 break;
1510 default:
1511 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1512 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001513 }
1514
He Yunchaoced53ae2016-11-29 15:00:51 +08001515 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1516 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001517}
1518
Austin Kinrossbc781f32015-10-26 09:27:38 -07001519bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1520{
1521 if (!context->getExtensions().vertexArrayObject)
1522 {
Jamie Madill437fa652016-05-03 15:13:24 -04001523 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001524 return false;
1525 }
1526
1527 return ValidateBindVertexArrayBase(context, array);
1528}
1529
1530bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1531{
1532 if (!context->getExtensions().vertexArrayObject)
1533 {
Jamie Madill437fa652016-05-03 15:13:24 -04001534 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001535 return false;
1536 }
1537
Olli Etuaho41997e72016-03-10 13:38:39 +02001538 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001539}
1540
1541bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1542{
1543 if (!context->getExtensions().vertexArrayObject)
1544 {
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001546 return false;
1547 }
1548
Olli Etuaho41997e72016-03-10 13:38:39 +02001549 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001550}
1551
1552bool ValidateIsVertexArrayOES(Context *context)
1553{
1554 if (!context->getExtensions().vertexArrayObject)
1555 {
Jamie Madill437fa652016-05-03 15:13:24 -04001556 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001557 return false;
1558 }
1559
1560 return true;
1561}
Geoff Langc5629752015-12-07 16:29:04 -05001562
1563bool ValidateProgramBinaryOES(Context *context,
1564 GLuint program,
1565 GLenum binaryFormat,
1566 const void *binary,
1567 GLint length)
1568{
1569 if (!context->getExtensions().getProgramBinary)
1570 {
Jamie Madill437fa652016-05-03 15:13:24 -04001571 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001572 return false;
1573 }
1574
1575 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1576}
1577
1578bool ValidateGetProgramBinaryOES(Context *context,
1579 GLuint program,
1580 GLsizei bufSize,
1581 GLsizei *length,
1582 GLenum *binaryFormat,
1583 void *binary)
1584{
1585 if (!context->getExtensions().getProgramBinary)
1586 {
Jamie Madill437fa652016-05-03 15:13:24 -04001587 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001588 return false;
1589 }
1590
1591 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1592}
Geoff Lange102fee2015-12-10 11:23:30 -05001593
Geoff Lang70d0f492015-12-10 17:45:46 -05001594static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1595{
1596 switch (source)
1597 {
1598 case GL_DEBUG_SOURCE_API:
1599 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1600 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1601 case GL_DEBUG_SOURCE_OTHER:
1602 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1603 return !mustBeThirdPartyOrApplication;
1604
1605 case GL_DEBUG_SOURCE_THIRD_PARTY:
1606 case GL_DEBUG_SOURCE_APPLICATION:
1607 return true;
1608
1609 default:
1610 return false;
1611 }
1612}
1613
1614static bool ValidDebugType(GLenum type)
1615{
1616 switch (type)
1617 {
1618 case GL_DEBUG_TYPE_ERROR:
1619 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1620 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1621 case GL_DEBUG_TYPE_PERFORMANCE:
1622 case GL_DEBUG_TYPE_PORTABILITY:
1623 case GL_DEBUG_TYPE_OTHER:
1624 case GL_DEBUG_TYPE_MARKER:
1625 case GL_DEBUG_TYPE_PUSH_GROUP:
1626 case GL_DEBUG_TYPE_POP_GROUP:
1627 return true;
1628
1629 default:
1630 return false;
1631 }
1632}
1633
1634static bool ValidDebugSeverity(GLenum severity)
1635{
1636 switch (severity)
1637 {
1638 case GL_DEBUG_SEVERITY_HIGH:
1639 case GL_DEBUG_SEVERITY_MEDIUM:
1640 case GL_DEBUG_SEVERITY_LOW:
1641 case GL_DEBUG_SEVERITY_NOTIFICATION:
1642 return true;
1643
1644 default:
1645 return false;
1646 }
1647}
1648
Geoff Lange102fee2015-12-10 11:23:30 -05001649bool ValidateDebugMessageControlKHR(Context *context,
1650 GLenum source,
1651 GLenum type,
1652 GLenum severity,
1653 GLsizei count,
1654 const GLuint *ids,
1655 GLboolean enabled)
1656{
1657 if (!context->getExtensions().debug)
1658 {
Jamie Madill437fa652016-05-03 15:13:24 -04001659 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001660 return false;
1661 }
1662
Geoff Lang70d0f492015-12-10 17:45:46 -05001663 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1664 {
Jamie Madill437fa652016-05-03 15:13:24 -04001665 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001666 return false;
1667 }
1668
1669 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1670 {
Jamie Madill437fa652016-05-03 15:13:24 -04001671 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001672 return false;
1673 }
1674
1675 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1676 {
Jamie Madill437fa652016-05-03 15:13:24 -04001677 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001678 return false;
1679 }
1680
1681 if (count > 0)
1682 {
1683 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001686 GL_INVALID_OPERATION,
1687 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1688 return false;
1689 }
1690
1691 if (severity != GL_DONT_CARE)
1692 {
Jamie Madill437fa652016-05-03 15:13:24 -04001693 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001694 Error(GL_INVALID_OPERATION,
1695 "If count is greater than zero, severity must be GL_DONT_CARE."));
1696 return false;
1697 }
1698 }
1699
Geoff Lange102fee2015-12-10 11:23:30 -05001700 return true;
1701}
1702
1703bool ValidateDebugMessageInsertKHR(Context *context,
1704 GLenum source,
1705 GLenum type,
1706 GLuint id,
1707 GLenum severity,
1708 GLsizei length,
1709 const GLchar *buf)
1710{
1711 if (!context->getExtensions().debug)
1712 {
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001714 return false;
1715 }
1716
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001717 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001718 {
1719 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1720 // not generate an error.
1721 return false;
1722 }
1723
1724 if (!ValidDebugSeverity(severity))
1725 {
Jamie Madill437fa652016-05-03 15:13:24 -04001726 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001727 return false;
1728 }
1729
1730 if (!ValidDebugType(type))
1731 {
Jamie Madill437fa652016-05-03 15:13:24 -04001732 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001733 return false;
1734 }
1735
1736 if (!ValidDebugSource(source, true))
1737 {
Jamie Madill437fa652016-05-03 15:13:24 -04001738 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001739 return false;
1740 }
1741
1742 size_t messageLength = (length < 0) ? strlen(buf) : length;
1743 if (messageLength > context->getExtensions().maxDebugMessageLength)
1744 {
Jamie Madill437fa652016-05-03 15:13:24 -04001745 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001746 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1747 return false;
1748 }
1749
Geoff Lange102fee2015-12-10 11:23:30 -05001750 return true;
1751}
1752
1753bool ValidateDebugMessageCallbackKHR(Context *context,
1754 GLDEBUGPROCKHR callback,
1755 const void *userParam)
1756{
1757 if (!context->getExtensions().debug)
1758 {
Jamie Madill437fa652016-05-03 15:13:24 -04001759 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001760 return false;
1761 }
1762
Geoff Lange102fee2015-12-10 11:23:30 -05001763 return true;
1764}
1765
1766bool ValidateGetDebugMessageLogKHR(Context *context,
1767 GLuint count,
1768 GLsizei bufSize,
1769 GLenum *sources,
1770 GLenum *types,
1771 GLuint *ids,
1772 GLenum *severities,
1773 GLsizei *lengths,
1774 GLchar *messageLog)
1775{
1776 if (!context->getExtensions().debug)
1777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001779 return false;
1780 }
1781
Geoff Lang70d0f492015-12-10 17:45:46 -05001782 if (bufSize < 0 && messageLog != nullptr)
1783 {
Jamie Madill437fa652016-05-03 15:13:24 -04001784 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001785 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1786 return false;
1787 }
1788
Geoff Lange102fee2015-12-10 11:23:30 -05001789 return true;
1790}
1791
1792bool ValidatePushDebugGroupKHR(Context *context,
1793 GLenum source,
1794 GLuint id,
1795 GLsizei length,
1796 const GLchar *message)
1797{
1798 if (!context->getExtensions().debug)
1799 {
Jamie Madill437fa652016-05-03 15:13:24 -04001800 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001801 return false;
1802 }
1803
Geoff Lang70d0f492015-12-10 17:45:46 -05001804 if (!ValidDebugSource(source, true))
1805 {
Jamie Madill437fa652016-05-03 15:13:24 -04001806 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001807 return false;
1808 }
1809
1810 size_t messageLength = (length < 0) ? strlen(message) : length;
1811 if (messageLength > context->getExtensions().maxDebugMessageLength)
1812 {
Jamie Madill437fa652016-05-03 15:13:24 -04001813 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001814 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1815 return false;
1816 }
1817
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001818 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001819 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1820 {
Jamie Madill437fa652016-05-03 15:13:24 -04001821 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001822 Error(GL_STACK_OVERFLOW,
1823 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1824 return false;
1825 }
1826
Geoff Lange102fee2015-12-10 11:23:30 -05001827 return true;
1828}
1829
1830bool ValidatePopDebugGroupKHR(Context *context)
1831{
1832 if (!context->getExtensions().debug)
1833 {
Jamie Madill437fa652016-05-03 15:13:24 -04001834 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001835 return false;
1836 }
1837
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001838 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001839 if (currentStackSize <= 1)
1840 {
Jamie Madill437fa652016-05-03 15:13:24 -04001841 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001842 return false;
1843 }
1844
1845 return true;
1846}
1847
1848static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1849{
1850 switch (identifier)
1851 {
1852 case GL_BUFFER:
1853 if (context->getBuffer(name) == nullptr)
1854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001856 return false;
1857 }
1858 return true;
1859
1860 case GL_SHADER:
1861 if (context->getShader(name) == nullptr)
1862 {
Jamie Madill437fa652016-05-03 15:13:24 -04001863 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001864 return false;
1865 }
1866 return true;
1867
1868 case GL_PROGRAM:
1869 if (context->getProgram(name) == nullptr)
1870 {
Jamie Madill437fa652016-05-03 15:13:24 -04001871 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001872 return false;
1873 }
1874 return true;
1875
1876 case GL_VERTEX_ARRAY:
1877 if (context->getVertexArray(name) == nullptr)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001880 return false;
1881 }
1882 return true;
1883
1884 case GL_QUERY:
1885 if (context->getQuery(name) == nullptr)
1886 {
Jamie Madill437fa652016-05-03 15:13:24 -04001887 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001888 return false;
1889 }
1890 return true;
1891
1892 case GL_TRANSFORM_FEEDBACK:
1893 if (context->getTransformFeedback(name) == nullptr)
1894 {
Jamie Madill437fa652016-05-03 15:13:24 -04001895 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001896 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1897 return false;
1898 }
1899 return true;
1900
1901 case GL_SAMPLER:
1902 if (context->getSampler(name) == nullptr)
1903 {
Jamie Madill437fa652016-05-03 15:13:24 -04001904 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001905 return false;
1906 }
1907 return true;
1908
1909 case GL_TEXTURE:
1910 if (context->getTexture(name) == nullptr)
1911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001913 return false;
1914 }
1915 return true;
1916
1917 case GL_RENDERBUFFER:
1918 if (context->getRenderbuffer(name) == nullptr)
1919 {
Jamie Madill437fa652016-05-03 15:13:24 -04001920 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001921 return false;
1922 }
1923 return true;
1924
1925 case GL_FRAMEBUFFER:
1926 if (context->getFramebuffer(name) == nullptr)
1927 {
Jamie Madill437fa652016-05-03 15:13:24 -04001928 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001929 return false;
1930 }
1931 return true;
1932
1933 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001934 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001935 return false;
1936 }
Geoff Lange102fee2015-12-10 11:23:30 -05001937}
1938
Martin Radev9d901792016-07-15 15:58:58 +03001939static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1940{
1941 size_t labelLength = 0;
1942
1943 if (length < 0)
1944 {
1945 if (label != nullptr)
1946 {
1947 labelLength = strlen(label);
1948 }
1949 }
1950 else
1951 {
1952 labelLength = static_cast<size_t>(length);
1953 }
1954
1955 if (labelLength > context->getExtensions().maxLabelLength)
1956 {
1957 context->handleError(
1958 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1959 return false;
1960 }
1961
1962 return true;
1963}
1964
Geoff Lange102fee2015-12-10 11:23:30 -05001965bool ValidateObjectLabelKHR(Context *context,
1966 GLenum identifier,
1967 GLuint name,
1968 GLsizei length,
1969 const GLchar *label)
1970{
1971 if (!context->getExtensions().debug)
1972 {
Jamie Madill437fa652016-05-03 15:13:24 -04001973 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001974 return false;
1975 }
1976
Geoff Lang70d0f492015-12-10 17:45:46 -05001977 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1978 {
1979 return false;
1980 }
1981
Martin Radev9d901792016-07-15 15:58:58 +03001982 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001983 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001984 return false;
1985 }
1986
Geoff Lange102fee2015-12-10 11:23:30 -05001987 return true;
1988}
1989
1990bool ValidateGetObjectLabelKHR(Context *context,
1991 GLenum identifier,
1992 GLuint name,
1993 GLsizei bufSize,
1994 GLsizei *length,
1995 GLchar *label)
1996{
1997 if (!context->getExtensions().debug)
1998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002000 return false;
2001 }
2002
Geoff Lang70d0f492015-12-10 17:45:46 -05002003 if (bufSize < 0)
2004 {
Jamie Madill437fa652016-05-03 15:13:24 -04002005 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002006 return false;
2007 }
2008
2009 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2010 {
2011 return false;
2012 }
2013
Martin Radev9d901792016-07-15 15:58:58 +03002014 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002015}
2016
2017static bool ValidateObjectPtrName(Context *context, const void *ptr)
2018{
2019 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002022 return false;
2023 }
2024
Geoff Lange102fee2015-12-10 11:23:30 -05002025 return true;
2026}
2027
2028bool ValidateObjectPtrLabelKHR(Context *context,
2029 const void *ptr,
2030 GLsizei length,
2031 const GLchar *label)
2032{
2033 if (!context->getExtensions().debug)
2034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002036 return false;
2037 }
2038
Geoff Lang70d0f492015-12-10 17:45:46 -05002039 if (!ValidateObjectPtrName(context, ptr))
2040 {
2041 return false;
2042 }
2043
Martin Radev9d901792016-07-15 15:58:58 +03002044 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002045 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002046 return false;
2047 }
2048
Geoff Lange102fee2015-12-10 11:23:30 -05002049 return true;
2050}
2051
2052bool ValidateGetObjectPtrLabelKHR(Context *context,
2053 const void *ptr,
2054 GLsizei bufSize,
2055 GLsizei *length,
2056 GLchar *label)
2057{
2058 if (!context->getExtensions().debug)
2059 {
Jamie Madill437fa652016-05-03 15:13:24 -04002060 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002061 return false;
2062 }
2063
Geoff Lang70d0f492015-12-10 17:45:46 -05002064 if (bufSize < 0)
2065 {
Jamie Madill437fa652016-05-03 15:13:24 -04002066 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002067 return false;
2068 }
2069
2070 if (!ValidateObjectPtrName(context, ptr))
2071 {
2072 return false;
2073 }
2074
Martin Radev9d901792016-07-15 15:58:58 +03002075 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002076}
2077
2078bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2079{
2080 if (!context->getExtensions().debug)
2081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002083 return false;
2084 }
2085
Geoff Lang70d0f492015-12-10 17:45:46 -05002086 // TODO: represent this in Context::getQueryParameterInfo.
2087 switch (pname)
2088 {
2089 case GL_DEBUG_CALLBACK_FUNCTION:
2090 case GL_DEBUG_CALLBACK_USER_PARAM:
2091 break;
2092
2093 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002094 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002095 return false;
2096 }
2097
Geoff Lange102fee2015-12-10 11:23:30 -05002098 return true;
2099}
Jamie Madillc29968b2016-01-20 11:17:23 -05002100
2101bool ValidateBlitFramebufferANGLE(Context *context,
2102 GLint srcX0,
2103 GLint srcY0,
2104 GLint srcX1,
2105 GLint srcY1,
2106 GLint dstX0,
2107 GLint dstY0,
2108 GLint dstX1,
2109 GLint dstY1,
2110 GLbitfield mask,
2111 GLenum filter)
2112{
2113 if (!context->getExtensions().framebufferBlit)
2114 {
Jamie Madill437fa652016-05-03 15:13:24 -04002115 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002116 return false;
2117 }
2118
2119 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2120 {
2121 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04002122 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05002123 GL_INVALID_OPERATION,
2124 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
2125 return false;
2126 }
2127
2128 if (filter == GL_LINEAR)
2129 {
Jamie Madill437fa652016-05-03 15:13:24 -04002130 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002131 return false;
2132 }
2133
Jamie Madill51f40ec2016-06-15 14:06:00 -04002134 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2135 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002136
2137 if (mask & GL_COLOR_BUFFER_BIT)
2138 {
2139 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2140 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2141
2142 if (readColorAttachment && drawColorAttachment)
2143 {
2144 if (!(readColorAttachment->type() == GL_TEXTURE &&
2145 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2146 readColorAttachment->type() != GL_RENDERBUFFER &&
2147 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2148 {
Jamie Madill437fa652016-05-03 15:13:24 -04002149 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002150 return false;
2151 }
2152
Geoff Langa15472a2015-08-11 11:48:03 -04002153 for (size_t drawbufferIdx = 0;
2154 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002155 {
Geoff Langa15472a2015-08-11 11:48:03 -04002156 const FramebufferAttachment *attachment =
2157 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2158 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002159 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002160 if (!(attachment->type() == GL_TEXTURE &&
2161 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2162 attachment->type() != GL_RENDERBUFFER &&
2163 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2164 {
Jamie Madill437fa652016-05-03 15:13:24 -04002165 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002166 return false;
2167 }
2168
2169 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002170 if (!Format::SameSized(attachment->getFormat(),
2171 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002172 {
Jamie Madill437fa652016-05-03 15:13:24 -04002173 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002174 return false;
2175 }
2176 }
2177 }
2178
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002179 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002180 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2181 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2182 {
Jamie Madill437fa652016-05-03 15:13:24 -04002183 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002184 return false;
2185 }
2186 }
2187 }
2188
2189 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2190 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2191 for (size_t i = 0; i < 2; i++)
2192 {
2193 if (mask & masks[i])
2194 {
2195 const FramebufferAttachment *readBuffer =
2196 readFramebuffer->getAttachment(attachments[i]);
2197 const FramebufferAttachment *drawBuffer =
2198 drawFramebuffer->getAttachment(attachments[i]);
2199
2200 if (readBuffer && drawBuffer)
2201 {
2202 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2203 dstX0, dstY0, dstX1, dstY1))
2204 {
2205 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05002206 context->handleError(Error(GL_INVALID_OPERATION,
2207 "Only whole-buffer depth and stencil blits are "
2208 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002209 return false;
2210 }
2211
2212 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2213 {
Jamie Madill437fa652016-05-03 15:13:24 -04002214 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002215 return false;
2216 }
2217 }
2218 }
2219 }
2220
2221 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2222 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002223}
Jamie Madillc29968b2016-01-20 11:17:23 -05002224
2225bool ValidateClear(ValidationContext *context, GLbitfield mask)
2226{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002227 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002228 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002229 {
Jamie Madill437fa652016-05-03 15:13:24 -04002230 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002231 return false;
2232 }
2233
2234 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2235 {
Jamie Madill437fa652016-05-03 15:13:24 -04002236 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05002237 return false;
2238 }
2239
Geoff Lang76e65652017-03-27 14:58:02 -04002240 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2241 {
2242 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2243 GL_SIGNED_NORMALIZED};
2244
2245 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2246 drawBufferIdx++)
2247 {
2248 if (!ValidateWebGLFramebufferAttachmentClearType(
2249 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2250 {
2251 return false;
2252 }
2253 }
2254 }
2255
Jamie Madillc29968b2016-01-20 11:17:23 -05002256 return true;
2257}
2258
2259bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2260{
2261 if (!context->getExtensions().drawBuffers)
2262 {
Jamie Madill437fa652016-05-03 15:13:24 -04002263 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002264 return false;
2265 }
2266
2267 return ValidateDrawBuffersBase(context, n, bufs);
2268}
2269
Jamie Madill73a84962016-02-12 09:27:23 -05002270bool ValidateTexImage2D(Context *context,
2271 GLenum target,
2272 GLint level,
2273 GLint internalformat,
2274 GLsizei width,
2275 GLsizei height,
2276 GLint border,
2277 GLenum format,
2278 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002279 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002280{
Martin Radev1be913c2016-07-11 17:59:16 +03002281 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002282 {
2283 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002284 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002285 }
2286
Martin Radev1be913c2016-07-11 17:59:16 +03002287 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002288 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002289 0, 0, width, height, 1, border, format, type, -1,
2290 pixels);
2291}
2292
2293bool ValidateTexImage2DRobust(Context *context,
2294 GLenum target,
2295 GLint level,
2296 GLint internalformat,
2297 GLsizei width,
2298 GLsizei height,
2299 GLint border,
2300 GLenum format,
2301 GLenum type,
2302 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002303 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002304{
2305 if (!ValidateRobustEntryPoint(context, bufSize))
2306 {
2307 return false;
2308 }
2309
2310 if (context->getClientMajorVersion() < 3)
2311 {
2312 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2313 0, 0, width, height, border, format, type, bufSize,
2314 pixels);
2315 }
2316
2317 ASSERT(context->getClientMajorVersion() >= 3);
2318 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2319 0, 0, width, height, 1, border, format, type, bufSize,
2320 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002321}
2322
2323bool ValidateTexSubImage2D(Context *context,
2324 GLenum target,
2325 GLint level,
2326 GLint xoffset,
2327 GLint yoffset,
2328 GLsizei width,
2329 GLsizei height,
2330 GLenum format,
2331 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002332 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002333{
2334
Martin Radev1be913c2016-07-11 17:59:16 +03002335 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002336 {
2337 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002338 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002339 }
2340
Martin Radev1be913c2016-07-11 17:59:16 +03002341 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002342 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002343 yoffset, 0, width, height, 1, 0, format, type, -1,
2344 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002345}
2346
Geoff Langc52f6f12016-10-14 10:18:00 -04002347bool ValidateTexSubImage2DRobustANGLE(Context *context,
2348 GLenum target,
2349 GLint level,
2350 GLint xoffset,
2351 GLint yoffset,
2352 GLsizei width,
2353 GLsizei height,
2354 GLenum format,
2355 GLenum type,
2356 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002357 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002358{
2359 if (!ValidateRobustEntryPoint(context, bufSize))
2360 {
2361 return false;
2362 }
2363
2364 if (context->getClientMajorVersion() < 3)
2365 {
2366 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2367 yoffset, width, height, 0, format, type, bufSize,
2368 pixels);
2369 }
2370
2371 ASSERT(context->getClientMajorVersion() >= 3);
2372 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2373 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2374 pixels);
2375}
2376
Jamie Madill73a84962016-02-12 09:27:23 -05002377bool ValidateCompressedTexImage2D(Context *context,
2378 GLenum target,
2379 GLint level,
2380 GLenum internalformat,
2381 GLsizei width,
2382 GLsizei height,
2383 GLint border,
2384 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002385 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002386{
Martin Radev1be913c2016-07-11 17:59:16 +03002387 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002388 {
2389 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002390 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002391 {
2392 return false;
2393 }
2394 }
2395 else
2396 {
Martin Radev1be913c2016-07-11 17:59:16 +03002397 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002398 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002399 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002400 data))
2401 {
2402 return false;
2403 }
2404 }
2405
Geoff Langca271392017-04-05 12:30:00 -04002406 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002407 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002408 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002409 if (blockSizeOrErr.isError())
2410 {
2411 context->handleError(blockSizeOrErr.getError());
2412 return false;
2413 }
2414
2415 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002416 {
Jamie Madill437fa652016-05-03 15:13:24 -04002417 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002418 return false;
2419 }
2420
2421 return true;
2422}
2423
Corentin Wallezb2931602017-04-11 15:58:57 -04002424bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2425 GLenum target,
2426 GLint level,
2427 GLenum internalformat,
2428 GLsizei width,
2429 GLsizei height,
2430 GLint border,
2431 GLsizei imageSize,
2432 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002433 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002434{
2435 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2436 {
2437 return false;
2438 }
2439
2440 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2441 border, imageSize, data);
2442}
2443bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2444 GLenum target,
2445 GLint level,
2446 GLint xoffset,
2447 GLint yoffset,
2448 GLsizei width,
2449 GLsizei height,
2450 GLenum format,
2451 GLsizei imageSize,
2452 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002453 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002454{
2455 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2456 {
2457 return false;
2458 }
2459
2460 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2461 format, imageSize, data);
2462}
2463
Jamie Madill73a84962016-02-12 09:27:23 -05002464bool ValidateCompressedTexSubImage2D(Context *context,
2465 GLenum target,
2466 GLint level,
2467 GLint xoffset,
2468 GLint yoffset,
2469 GLsizei width,
2470 GLsizei height,
2471 GLenum format,
2472 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002473 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002474{
Martin Radev1be913c2016-07-11 17:59:16 +03002475 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002476 {
2477 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002478 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002479 {
2480 return false;
2481 }
2482 }
2483 else
2484 {
Martin Radev1be913c2016-07-11 17:59:16 +03002485 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002486 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002487 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002488 data))
2489 {
2490 return false;
2491 }
2492 }
2493
Geoff Langca271392017-04-05 12:30:00 -04002494 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002495 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002496 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002497 if (blockSizeOrErr.isError())
2498 {
2499 context->handleError(blockSizeOrErr.getError());
2500 return false;
2501 }
2502
2503 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002504 {
Jamie Madill437fa652016-05-03 15:13:24 -04002505 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002506 return false;
2507 }
2508
2509 return true;
2510}
2511
Olli Etuaho4f667482016-03-30 15:56:35 +03002512bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2513{
Geoff Lang496c02d2016-10-20 11:38:11 -07002514 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002515}
2516
2517bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2518{
2519 if (!context->getExtensions().mapBuffer)
2520 {
Jamie Madill437fa652016-05-03 15:13:24 -04002521 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002522 return false;
2523 }
2524
2525 if (!ValidBufferTarget(context, target))
2526 {
Jamie Madill437fa652016-05-03 15:13:24 -04002527 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002528 return false;
2529 }
2530
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002531 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002532
2533 if (buffer == nullptr)
2534 {
Jamie Madill437fa652016-05-03 15:13:24 -04002535 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002536 return false;
2537 }
2538
2539 if (access != GL_WRITE_ONLY_OES)
2540 {
Jamie Madill437fa652016-05-03 15:13:24 -04002541 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002542 return false;
2543 }
2544
2545 if (buffer->isMapped())
2546 {
Jamie Madill437fa652016-05-03 15:13:24 -04002547 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002548 return false;
2549 }
2550
2551 return true;
2552}
2553
2554bool ValidateUnmapBufferOES(Context *context, GLenum target)
2555{
2556 if (!context->getExtensions().mapBuffer)
2557 {
Jamie Madill437fa652016-05-03 15:13:24 -04002558 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002559 return false;
2560 }
2561
2562 return ValidateUnmapBufferBase(context, target);
2563}
2564
2565bool ValidateMapBufferRangeEXT(Context *context,
2566 GLenum target,
2567 GLintptr offset,
2568 GLsizeiptr length,
2569 GLbitfield access)
2570{
2571 if (!context->getExtensions().mapBufferRange)
2572 {
Jamie Madill437fa652016-05-03 15:13:24 -04002573 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002574 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2575 return false;
2576 }
2577
2578 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2579}
2580
2581bool ValidateFlushMappedBufferRangeEXT(Context *context,
2582 GLenum target,
2583 GLintptr offset,
2584 GLsizeiptr length)
2585{
2586 if (!context->getExtensions().mapBufferRange)
2587 {
Jamie Madill437fa652016-05-03 15:13:24 -04002588 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002589 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2590 return false;
2591 }
2592
2593 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2594}
2595
Ian Ewell54f87462016-03-10 13:47:21 -05002596bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2597{
2598 Texture *textureObject = context->getTexture(texture);
2599 if (textureObject && textureObject->getTarget() != target && texture != 0)
2600 {
Jamie Madill437fa652016-05-03 15:13:24 -04002601 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002602 return false;
2603 }
2604
Geoff Langf41a7152016-09-19 15:11:17 -04002605 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2606 !context->isTextureGenerated(texture))
2607 {
2608 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2609 return false;
2610 }
2611
Ian Ewell54f87462016-03-10 13:47:21 -05002612 switch (target)
2613 {
2614 case GL_TEXTURE_2D:
2615 case GL_TEXTURE_CUBE_MAP:
2616 break;
2617
2618 case GL_TEXTURE_3D:
2619 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002620 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002621 {
Jamie Madill437fa652016-05-03 15:13:24 -04002622 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002623 return false;
2624 }
2625 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002626
2627 case GL_TEXTURE_2D_MULTISAMPLE:
2628 if (context->getClientVersion() < Version(3, 1))
2629 {
2630 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2631 return false;
2632 }
Geoff Lang3b573612016-10-31 14:08:10 -04002633 break;
2634
Ian Ewell54f87462016-03-10 13:47:21 -05002635 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002636 if (!context->getExtensions().eglImageExternal &&
2637 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002638 {
Jamie Madill437fa652016-05-03 15:13:24 -04002639 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002640 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2641 return false;
2642 }
2643 break;
2644 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002646 return false;
2647 }
2648
2649 return true;
2650}
2651
Geoff Langd8605522016-04-13 10:19:12 -04002652bool ValidateBindUniformLocationCHROMIUM(Context *context,
2653 GLuint program,
2654 GLint location,
2655 const GLchar *name)
2656{
2657 if (!context->getExtensions().bindUniformLocation)
2658 {
Jamie Madill437fa652016-05-03 15:13:24 -04002659 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002660 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2661 return false;
2662 }
2663
2664 Program *programObject = GetValidProgram(context, program);
2665 if (!programObject)
2666 {
2667 return false;
2668 }
2669
2670 if (location < 0)
2671 {
Jamie Madill437fa652016-05-03 15:13:24 -04002672 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002673 return false;
2674 }
2675
2676 const Caps &caps = context->getCaps();
2677 if (static_cast<size_t>(location) >=
2678 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2679 {
Jamie Madill437fa652016-05-03 15:13:24 -04002680 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002681 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2682 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2683 return false;
2684 }
2685
Geoff Langfc32e8b2017-05-31 14:16:59 -04002686 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2687 // shader-related entry points
2688 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
2689 {
2690 context->handleError(Error(GL_INVALID_VALUE, "Uniform name contains invalid characters"));
2691 return false;
2692 }
2693
Geoff Langd8605522016-04-13 10:19:12 -04002694 if (strncmp(name, "gl_", 3) == 0)
2695 {
Jamie Madill437fa652016-05-03 15:13:24 -04002696 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002697 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2698 return false;
2699 }
2700
2701 return true;
2702}
2703
Jamie Madille2e406c2016-06-02 13:04:10 -04002704bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002705{
2706 if (!context->getExtensions().framebufferMixedSamples)
2707 {
2708 context->handleError(
2709 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2710 return false;
2711 }
2712 switch (components)
2713 {
2714 case GL_RGB:
2715 case GL_RGBA:
2716 case GL_ALPHA:
2717 case GL_NONE:
2718 break;
2719 default:
2720 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002721 Error(GL_INVALID_ENUM,
2722 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002723 return false;
2724 }
2725
2726 return true;
2727}
2728
Sami Väisänene45e53b2016-05-25 10:36:04 +03002729// CHROMIUM_path_rendering
2730
2731bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2732{
2733 if (!context->getExtensions().pathRendering)
2734 {
2735 context->handleError(
2736 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2737 return false;
2738 }
2739 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2740 {
2741 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2742 return false;
2743 }
2744 if (matrix == nullptr)
2745 {
2746 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2747 return false;
2748 }
2749 return true;
2750}
2751
2752bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2753{
2754 if (!context->getExtensions().pathRendering)
2755 {
2756 context->handleError(
2757 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2758 return false;
2759 }
2760 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2761 {
2762 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2763 return false;
2764 }
2765 return true;
2766}
2767
2768bool ValidateGenPaths(Context *context, GLsizei range)
2769{
2770 if (!context->getExtensions().pathRendering)
2771 {
2772 context->handleError(
2773 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2774 return false;
2775 }
2776
2777 // range = 0 is undefined in NV_path_rendering.
2778 // we add stricter semantic check here and require a non zero positive range.
2779 if (range <= 0)
2780 {
2781 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2782 return false;
2783 }
2784
2785 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2786 {
2787 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2788 return false;
2789 }
2790
2791 return true;
2792}
2793
2794bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2795{
2796 if (!context->getExtensions().pathRendering)
2797 {
2798 context->handleError(
2799 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2800 return false;
2801 }
2802
2803 // range = 0 is undefined in NV_path_rendering.
2804 // we add stricter semantic check here and require a non zero positive range.
2805 if (range <= 0)
2806 {
2807 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2808 return false;
2809 }
2810
2811 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2812 checkedRange += range;
2813
2814 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2815 {
2816 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2817 return false;
2818 }
2819 return true;
2820}
2821
2822bool ValidatePathCommands(Context *context,
2823 GLuint path,
2824 GLsizei numCommands,
2825 const GLubyte *commands,
2826 GLsizei numCoords,
2827 GLenum coordType,
2828 const void *coords)
2829{
2830 if (!context->getExtensions().pathRendering)
2831 {
2832 context->handleError(
2833 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2834 return false;
2835 }
2836 if (!context->hasPath(path))
2837 {
2838 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2839 return false;
2840 }
2841
2842 if (numCommands < 0)
2843 {
2844 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2845 return false;
2846 }
2847 else if (numCommands > 0)
2848 {
2849 if (!commands)
2850 {
2851 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2852 return false;
2853 }
2854 }
2855
2856 if (numCoords < 0)
2857 {
2858 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2859 return false;
2860 }
2861 else if (numCoords > 0)
2862 {
2863 if (!coords)
2864 {
2865 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2866 return false;
2867 }
2868 }
2869
2870 std::uint32_t coordTypeSize = 0;
2871 switch (coordType)
2872 {
2873 case GL_BYTE:
2874 coordTypeSize = sizeof(GLbyte);
2875 break;
2876
2877 case GL_UNSIGNED_BYTE:
2878 coordTypeSize = sizeof(GLubyte);
2879 break;
2880
2881 case GL_SHORT:
2882 coordTypeSize = sizeof(GLshort);
2883 break;
2884
2885 case GL_UNSIGNED_SHORT:
2886 coordTypeSize = sizeof(GLushort);
2887 break;
2888
2889 case GL_FLOAT:
2890 coordTypeSize = sizeof(GLfloat);
2891 break;
2892
2893 default:
2894 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2895 return false;
2896 }
2897
2898 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2899 checkedSize += (coordTypeSize * numCoords);
2900 if (!checkedSize.IsValid())
2901 {
2902 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2903 return false;
2904 }
2905
2906 // early return skips command data validation when it doesn't exist.
2907 if (!commands)
2908 return true;
2909
2910 GLsizei expectedNumCoords = 0;
2911 for (GLsizei i = 0; i < numCommands; ++i)
2912 {
2913 switch (commands[i])
2914 {
2915 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2916 break;
2917 case GL_MOVE_TO_CHROMIUM:
2918 case GL_LINE_TO_CHROMIUM:
2919 expectedNumCoords += 2;
2920 break;
2921 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2922 expectedNumCoords += 4;
2923 break;
2924 case GL_CUBIC_CURVE_TO_CHROMIUM:
2925 expectedNumCoords += 6;
2926 break;
2927 case GL_CONIC_CURVE_TO_CHROMIUM:
2928 expectedNumCoords += 5;
2929 break;
2930 default:
2931 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2932 return false;
2933 }
2934 }
2935 if (expectedNumCoords != numCoords)
2936 {
2937 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2938 return false;
2939 }
2940
2941 return true;
2942}
2943
2944bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2945{
2946 if (!context->getExtensions().pathRendering)
2947 {
2948 context->handleError(
2949 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2950 return false;
2951 }
2952 if (!context->hasPath(path))
2953 {
2954 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2955 return false;
2956 }
2957
2958 switch (pname)
2959 {
2960 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2961 if (value < 0.0f)
2962 {
2963 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2964 return false;
2965 }
2966 break;
2967 case GL_PATH_END_CAPS_CHROMIUM:
2968 switch (static_cast<GLenum>(value))
2969 {
2970 case GL_FLAT_CHROMIUM:
2971 case GL_SQUARE_CHROMIUM:
2972 case GL_ROUND_CHROMIUM:
2973 break;
2974 default:
2975 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2976 return false;
2977 }
2978 break;
2979 case GL_PATH_JOIN_STYLE_CHROMIUM:
2980 switch (static_cast<GLenum>(value))
2981 {
2982 case GL_MITER_REVERT_CHROMIUM:
2983 case GL_BEVEL_CHROMIUM:
2984 case GL_ROUND_CHROMIUM:
2985 break;
2986 default:
2987 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2988 return false;
2989 }
2990 case GL_PATH_MITER_LIMIT_CHROMIUM:
2991 if (value < 0.0f)
2992 {
2993 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2994 return false;
2995 }
2996 break;
2997
2998 case GL_PATH_STROKE_BOUND_CHROMIUM:
2999 // no errors, only clamping.
3000 break;
3001
3002 default:
3003 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
3004 return false;
3005 }
3006 return true;
3007}
3008
3009bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3010{
3011 if (!context->getExtensions().pathRendering)
3012 {
3013 context->handleError(
3014 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3015 return false;
3016 }
3017
3018 if (!context->hasPath(path))
3019 {
3020 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3021 return false;
3022 }
3023 if (!value)
3024 {
3025 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
3026 return false;
3027 }
3028
3029 switch (pname)
3030 {
3031 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3032 case GL_PATH_END_CAPS_CHROMIUM:
3033 case GL_PATH_JOIN_STYLE_CHROMIUM:
3034 case GL_PATH_MITER_LIMIT_CHROMIUM:
3035 case GL_PATH_STROKE_BOUND_CHROMIUM:
3036 break;
3037
3038 default:
3039 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
3040 return false;
3041 }
3042
3043 return true;
3044}
3045
3046bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3047{
3048 if (!context->getExtensions().pathRendering)
3049 {
3050 context->handleError(
3051 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3052 return false;
3053 }
3054
3055 switch (func)
3056 {
3057 case GL_NEVER:
3058 case GL_ALWAYS:
3059 case GL_LESS:
3060 case GL_LEQUAL:
3061 case GL_EQUAL:
3062 case GL_GEQUAL:
3063 case GL_GREATER:
3064 case GL_NOTEQUAL:
3065 break;
3066 default:
3067 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
3068 return false;
3069 }
3070
3071 return true;
3072}
3073
3074// Note that the spec specifies that for the path drawing commands
3075// if the path object is not an existing path object the command
3076// does nothing and no error is generated.
3077// However if the path object exists but has not been specified any
3078// commands then an error is generated.
3079
3080bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3081{
3082 if (!context->getExtensions().pathRendering)
3083 {
3084 context->handleError(
3085 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3086 return false;
3087 }
3088 if (context->hasPath(path) && !context->hasPathData(path))
3089 {
3090 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3091 return false;
3092 }
3093
3094 switch (fillMode)
3095 {
3096 case GL_COUNT_UP_CHROMIUM:
3097 case GL_COUNT_DOWN_CHROMIUM:
3098 break;
3099 default:
3100 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3101 return false;
3102 }
3103
3104 if (!isPow2(mask + 1))
3105 {
3106 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3107 return false;
3108 }
3109
3110 return true;
3111}
3112
3113bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3114{
3115 if (!context->getExtensions().pathRendering)
3116 {
3117 context->handleError(
3118 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3119 return false;
3120 }
3121 if (context->hasPath(path) && !context->hasPathData(path))
3122 {
3123 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
3124 return false;
3125 }
3126
3127 return true;
3128}
3129
3130bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3131{
3132 if (!context->getExtensions().pathRendering)
3133 {
3134 context->handleError(
3135 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3136 return false;
3137 }
3138 if (context->hasPath(path) && !context->hasPathData(path))
3139 {
3140 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3141 return false;
3142 }
3143
3144 switch (coverMode)
3145 {
3146 case GL_CONVEX_HULL_CHROMIUM:
3147 case GL_BOUNDING_BOX_CHROMIUM:
3148 break;
3149 default:
3150 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3151 return false;
3152 }
3153 return true;
3154}
3155
3156bool ValidateStencilThenCoverFillPath(Context *context,
3157 GLuint path,
3158 GLenum fillMode,
3159 GLuint mask,
3160 GLenum coverMode)
3161{
3162 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3163 ValidateCoverPath(context, path, coverMode);
3164}
3165
3166bool ValidateStencilThenCoverStrokePath(Context *context,
3167 GLuint path,
3168 GLint reference,
3169 GLuint mask,
3170 GLenum coverMode)
3171{
3172 return ValidateStencilStrokePath(context, path, reference, mask) &&
3173 ValidateCoverPath(context, path, coverMode);
3174}
3175
3176bool ValidateIsPath(Context *context)
3177{
3178 if (!context->getExtensions().pathRendering)
3179 {
3180 context->handleError(
3181 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3182 return false;
3183 }
3184 return true;
3185}
3186
Sami Väisänend59ca052016-06-21 16:10:00 +03003187bool ValidateCoverFillPathInstanced(Context *context,
3188 GLsizei numPaths,
3189 GLenum pathNameType,
3190 const void *paths,
3191 GLuint pathBase,
3192 GLenum coverMode,
3193 GLenum transformType,
3194 const GLfloat *transformValues)
3195{
3196 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3197 transformType, transformValues))
3198 return false;
3199
3200 switch (coverMode)
3201 {
3202 case GL_CONVEX_HULL_CHROMIUM:
3203 case GL_BOUNDING_BOX_CHROMIUM:
3204 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3205 break;
3206 default:
3207 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3208 return false;
3209 }
3210
3211 return true;
3212}
3213
3214bool ValidateCoverStrokePathInstanced(Context *context,
3215 GLsizei numPaths,
3216 GLenum pathNameType,
3217 const void *paths,
3218 GLuint pathBase,
3219 GLenum coverMode,
3220 GLenum transformType,
3221 const GLfloat *transformValues)
3222{
3223 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3224 transformType, transformValues))
3225 return false;
3226
3227 switch (coverMode)
3228 {
3229 case GL_CONVEX_HULL_CHROMIUM:
3230 case GL_BOUNDING_BOX_CHROMIUM:
3231 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3232 break;
3233 default:
3234 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3235 return false;
3236 }
3237
3238 return true;
3239}
3240
3241bool ValidateStencilFillPathInstanced(Context *context,
3242 GLsizei numPaths,
3243 GLenum pathNameType,
3244 const void *paths,
3245 GLuint pathBase,
3246 GLenum fillMode,
3247 GLuint mask,
3248 GLenum transformType,
3249 const GLfloat *transformValues)
3250{
3251
3252 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3253 transformType, transformValues))
3254 return false;
3255
3256 switch (fillMode)
3257 {
3258 case GL_COUNT_UP_CHROMIUM:
3259 case GL_COUNT_DOWN_CHROMIUM:
3260 break;
3261 default:
3262 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3263 return false;
3264 }
3265 if (!isPow2(mask + 1))
3266 {
3267 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3268 return false;
3269 }
3270 return true;
3271}
3272
3273bool ValidateStencilStrokePathInstanced(Context *context,
3274 GLsizei numPaths,
3275 GLenum pathNameType,
3276 const void *paths,
3277 GLuint pathBase,
3278 GLint reference,
3279 GLuint mask,
3280 GLenum transformType,
3281 const GLfloat *transformValues)
3282{
3283 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3284 transformType, transformValues))
3285 return false;
3286
3287 // no more validation here.
3288
3289 return true;
3290}
3291
3292bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3293 GLsizei numPaths,
3294 GLenum pathNameType,
3295 const void *paths,
3296 GLuint pathBase,
3297 GLenum fillMode,
3298 GLuint mask,
3299 GLenum coverMode,
3300 GLenum transformType,
3301 const GLfloat *transformValues)
3302{
3303 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3304 transformType, transformValues))
3305 return false;
3306
3307 switch (coverMode)
3308 {
3309 case GL_CONVEX_HULL_CHROMIUM:
3310 case GL_BOUNDING_BOX_CHROMIUM:
3311 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3312 break;
3313 default:
3314 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3315 return false;
3316 }
3317
3318 switch (fillMode)
3319 {
3320 case GL_COUNT_UP_CHROMIUM:
3321 case GL_COUNT_DOWN_CHROMIUM:
3322 break;
3323 default:
3324 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3325 return false;
3326 }
3327 if (!isPow2(mask + 1))
3328 {
3329 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3330 return false;
3331 }
3332
3333 return true;
3334}
3335
3336bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3337 GLsizei numPaths,
3338 GLenum pathNameType,
3339 const void *paths,
3340 GLuint pathBase,
3341 GLint reference,
3342 GLuint mask,
3343 GLenum coverMode,
3344 GLenum transformType,
3345 const GLfloat *transformValues)
3346{
3347 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3348 transformType, transformValues))
3349 return false;
3350
3351 switch (coverMode)
3352 {
3353 case GL_CONVEX_HULL_CHROMIUM:
3354 case GL_BOUNDING_BOX_CHROMIUM:
3355 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3356 break;
3357 default:
3358 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3359 return false;
3360 }
3361
3362 return true;
3363}
3364
Sami Väisänen46eaa942016-06-29 10:26:37 +03003365bool ValidateBindFragmentInputLocation(Context *context,
3366 GLuint program,
3367 GLint location,
3368 const GLchar *name)
3369{
3370 if (!context->getExtensions().pathRendering)
3371 {
3372 context->handleError(
3373 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3374 return false;
3375 }
3376
3377 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3378 if (location >= MaxLocation)
3379 {
3380 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3381 return false;
3382 }
3383
3384 const auto *programObject = context->getProgram(program);
3385 if (!programObject)
3386 {
3387 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3388 return false;
3389 }
3390
3391 if (!name)
3392 {
3393 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3394 return false;
3395 }
3396
3397 if (angle::BeginsWith(name, "gl_"))
3398 {
3399 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3400 return false;
3401 }
3402
3403 return true;
3404}
3405
3406bool ValidateProgramPathFragmentInputGen(Context *context,
3407 GLuint program,
3408 GLint location,
3409 GLenum genMode,
3410 GLint components,
3411 const GLfloat *coeffs)
3412{
3413 if (!context->getExtensions().pathRendering)
3414 {
3415 context->handleError(
3416 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3417 return false;
3418 }
3419
3420 const auto *programObject = context->getProgram(program);
3421 if (!programObject || programObject->isFlaggedForDeletion())
3422 {
3423 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3424 return false;
3425 }
3426
3427 if (!programObject->isLinked())
3428 {
3429 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3430 return false;
3431 }
3432
3433 switch (genMode)
3434 {
3435 case GL_NONE:
3436 if (components != 0)
3437 {
3438 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3439 return false;
3440 }
3441 break;
3442
3443 case GL_OBJECT_LINEAR_CHROMIUM:
3444 case GL_EYE_LINEAR_CHROMIUM:
3445 case GL_CONSTANT_CHROMIUM:
3446 if (components < 1 || components > 4)
3447 {
3448 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3449 return false;
3450 }
3451 if (!coeffs)
3452 {
3453 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3454 return false;
3455 }
3456 break;
3457
3458 default:
3459 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3460 return false;
3461 }
3462
3463 // If the location is -1 then the command is silently ignored
3464 // and no further validation is needed.
3465 if (location == -1)
3466 return true;
3467
3468 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3469
3470 if (!binding.valid)
3471 {
3472 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3473 return false;
3474 }
3475
3476 if (binding.type != GL_NONE)
3477 {
3478 GLint expectedComponents = 0;
3479 switch (binding.type)
3480 {
3481 case GL_FLOAT:
3482 expectedComponents = 1;
3483 break;
3484 case GL_FLOAT_VEC2:
3485 expectedComponents = 2;
3486 break;
3487 case GL_FLOAT_VEC3:
3488 expectedComponents = 3;
3489 break;
3490 case GL_FLOAT_VEC4:
3491 expectedComponents = 4;
3492 break;
3493 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003494 context->handleError(
3495 Error(GL_INVALID_OPERATION,
3496 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003497 return false;
3498 }
3499 if (expectedComponents != components && genMode != GL_NONE)
3500 {
3501 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3502 return false;
3503 }
3504 }
3505 return true;
3506}
3507
Geoff Lang97073d12016-04-20 10:42:34 -07003508bool ValidateCopyTextureCHROMIUM(Context *context,
3509 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003510 GLint sourceLevel,
3511 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003512 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003513 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003514 GLint internalFormat,
3515 GLenum destType,
3516 GLboolean unpackFlipY,
3517 GLboolean unpackPremultiplyAlpha,
3518 GLboolean unpackUnmultiplyAlpha)
3519{
3520 if (!context->getExtensions().copyTexture)
3521 {
3522 context->handleError(
3523 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3524 return false;
3525 }
3526
Geoff Lang4f0e0032017-05-01 16:04:35 -04003527 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003528 if (source == nullptr)
3529 {
3530 context->handleError(
3531 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3532 return false;
3533 }
3534
3535 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3536 {
3537 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3538 return false;
3539 }
3540
3541 GLenum sourceTarget = source->getTarget();
3542 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003543
3544 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003545 {
Geoff Lang4f0e0032017-05-01 16:04:35 -04003546 context->handleError(Error(GL_INVALID_VALUE, "Source texture level is not valid."));
Geoff Lang97073d12016-04-20 10:42:34 -07003547 return false;
3548 }
3549
Geoff Lang4f0e0032017-05-01 16:04:35 -04003550 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3551 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3552 if (sourceWidth == 0 || sourceHeight == 0)
3553 {
3554 context->handleError(
3555 Error(GL_INVALID_VALUE, "The source level of the source texture must be defined."));
3556 return false;
3557 }
3558
3559 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3560 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003561 {
3562 context->handleError(
3563 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3564 return false;
3565 }
3566
Geoff Lang4f0e0032017-05-01 16:04:35 -04003567 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003568 if (dest == nullptr)
3569 {
3570 context->handleError(
3571 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3572 return false;
3573 }
3574
Geoff Lang4f0e0032017-05-01 16:04:35 -04003575 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003576 {
3577 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3578 return false;
3579 }
3580
Geoff Lang4f0e0032017-05-01 16:04:35 -04003581 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3582 sourceHeight))
3583 {
3584 context->handleError(Error(GL_INVALID_VALUE, "Destination texture level is not valid."));
3585 return false;
3586 }
3587
Geoff Lang97073d12016-04-20 10:42:34 -07003588 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3589 {
3590 context->handleError(
3591 Error(GL_INVALID_OPERATION,
3592 "Destination internal format and type combination is not valid."));
3593 return false;
3594 }
3595
Geoff Lang4f0e0032017-05-01 16:04:35 -04003596 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3597 {
3598 context->handleError(Error(
3599 GL_INVALID_VALUE, "Destination width and height must be equal for cube map textures."));
3600 return false;
3601 }
3602
Geoff Lang97073d12016-04-20 10:42:34 -07003603 if (dest->getImmutableFormat())
3604 {
3605 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3606 return false;
3607 }
3608
3609 return true;
3610}
3611
3612bool ValidateCopySubTextureCHROMIUM(Context *context,
3613 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003614 GLint sourceLevel,
3615 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003616 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003617 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003618 GLint xoffset,
3619 GLint yoffset,
3620 GLint x,
3621 GLint y,
3622 GLsizei width,
3623 GLsizei height,
3624 GLboolean unpackFlipY,
3625 GLboolean unpackPremultiplyAlpha,
3626 GLboolean unpackUnmultiplyAlpha)
3627{
3628 if (!context->getExtensions().copyTexture)
3629 {
3630 context->handleError(
3631 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3632 return false;
3633 }
3634
Geoff Lang4f0e0032017-05-01 16:04:35 -04003635 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003636 if (source == nullptr)
3637 {
3638 context->handleError(
3639 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3640 return false;
3641 }
3642
3643 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3644 {
3645 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3646 return false;
3647 }
3648
3649 GLenum sourceTarget = source->getTarget();
3650 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003651
3652 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3653 {
3654 context->handleError(Error(GL_INVALID_VALUE, "Source texture level is not valid."));
3655 return false;
3656 }
3657
3658 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3659 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003660 {
3661 context->handleError(
Geoff Lang4f0e0032017-05-01 16:04:35 -04003662 Error(GL_INVALID_VALUE, "The source level of the source texture must be defined."));
Geoff Lang97073d12016-04-20 10:42:34 -07003663 return false;
3664 }
3665
3666 if (x < 0 || y < 0)
3667 {
3668 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3669 return false;
3670 }
3671
3672 if (width < 0 || height < 0)
3673 {
3674 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3675 return false;
3676 }
3677
Geoff Lang4f0e0032017-05-01 16:04:35 -04003678 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3679 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003680 {
3681 context->handleError(
3682 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3683 return false;
3684 }
3685
Geoff Lang4f0e0032017-05-01 16:04:35 -04003686 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3687 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003688 {
3689 context->handleError(
3690 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3691 return false;
3692 }
3693
Geoff Lang4f0e0032017-05-01 16:04:35 -04003694 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003695 if (dest == nullptr)
3696 {
3697 context->handleError(
3698 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3699 return false;
3700 }
3701
Geoff Lang4f0e0032017-05-01 16:04:35 -04003702 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003703 {
3704 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3705 return false;
3706 }
3707
Geoff Lang4f0e0032017-05-01 16:04:35 -04003708 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003709 {
Geoff Lang4f0e0032017-05-01 16:04:35 -04003710 context->handleError(Error(GL_INVALID_VALUE, "Destination texture level is not valid."));
Geoff Lang97073d12016-04-20 10:42:34 -07003711 return false;
3712 }
3713
Geoff Lang4f0e0032017-05-01 16:04:35 -04003714 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3715 {
3716 context->handleError(Error(
3717 GL_INVALID_VALUE, "The destination level of the destination texture must be defined."));
3718 return false;
3719 }
3720
3721 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3722 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003723 {
3724 context->handleError(
3725 Error(GL_INVALID_OPERATION,
3726 "Destination internal format and type combination is not valid."));
3727 return false;
3728 }
3729
3730 if (xoffset < 0 || yoffset < 0)
3731 {
3732 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3733 return false;
3734 }
3735
Geoff Lang4f0e0032017-05-01 16:04:35 -04003736 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3737 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003738 {
3739 context->handleError(
3740 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3741 return false;
3742 }
3743
3744 return true;
3745}
3746
Geoff Lang47110bf2016-04-20 11:13:22 -07003747bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3748{
3749 if (!context->getExtensions().copyCompressedTexture)
3750 {
3751 context->handleError(Error(GL_INVALID_OPERATION,
3752 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3753 return false;
3754 }
3755
3756 const gl::Texture *source = context->getTexture(sourceId);
3757 if (source == nullptr)
3758 {
3759 context->handleError(
3760 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3761 return false;
3762 }
3763
3764 if (source->getTarget() != GL_TEXTURE_2D)
3765 {
3766 context->handleError(
3767 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3768 return false;
3769 }
3770
3771 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3772 {
3773 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3774 return false;
3775 }
3776
3777 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3778 if (!sourceFormat.info->compressed)
3779 {
3780 context->handleError(
3781 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3782 return false;
3783 }
3784
3785 const gl::Texture *dest = context->getTexture(destId);
3786 if (dest == nullptr)
3787 {
3788 context->handleError(
3789 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3790 return false;
3791 }
3792
3793 if (dest->getTarget() != GL_TEXTURE_2D)
3794 {
3795 context->handleError(
3796 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3797 return false;
3798 }
3799
3800 if (dest->getImmutableFormat())
3801 {
3802 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3803 return false;
3804 }
3805
3806 return true;
3807}
3808
Martin Radev4c4c8e72016-08-04 12:25:34 +03003809bool ValidateCreateShader(Context *context, GLenum type)
3810{
3811 switch (type)
3812 {
3813 case GL_VERTEX_SHADER:
3814 case GL_FRAGMENT_SHADER:
3815 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003816
Martin Radev4c4c8e72016-08-04 12:25:34 +03003817 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003818 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003819 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003820 context->handleError(
3821 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3822 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003823 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003824 break;
3825
Martin Radev4c4c8e72016-08-04 12:25:34 +03003826 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003827 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003828 return false;
3829 }
Jamie Madill29639852016-09-02 15:00:09 -04003830
3831 return true;
3832}
3833
3834bool ValidateBufferData(ValidationContext *context,
3835 GLenum target,
3836 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003837 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003838 GLenum usage)
3839{
3840 if (size < 0)
3841 {
3842 context->handleError(Error(GL_INVALID_VALUE));
3843 return false;
3844 }
3845
3846 switch (usage)
3847 {
3848 case GL_STREAM_DRAW:
3849 case GL_STATIC_DRAW:
3850 case GL_DYNAMIC_DRAW:
3851 break;
3852
3853 case GL_STREAM_READ:
3854 case GL_STREAM_COPY:
3855 case GL_STATIC_READ:
3856 case GL_STATIC_COPY:
3857 case GL_DYNAMIC_READ:
3858 case GL_DYNAMIC_COPY:
3859 if (context->getClientMajorVersion() < 3)
3860 {
3861 context->handleError(Error(GL_INVALID_ENUM));
3862 return false;
3863 }
3864 break;
3865
3866 default:
3867 context->handleError(Error(GL_INVALID_ENUM));
3868 return false;
3869 }
3870
3871 if (!ValidBufferTarget(context, target))
3872 {
3873 context->handleError(Error(GL_INVALID_ENUM));
3874 return false;
3875 }
3876
3877 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3878
3879 if (!buffer)
3880 {
3881 context->handleError(Error(GL_INVALID_OPERATION));
3882 return false;
3883 }
3884
3885 return true;
3886}
3887
3888bool ValidateBufferSubData(ValidationContext *context,
3889 GLenum target,
3890 GLintptr offset,
3891 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003892 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003893{
3894 if (size < 0 || offset < 0)
3895 {
3896 context->handleError(Error(GL_INVALID_VALUE));
3897 return false;
3898 }
3899
3900 if (!ValidBufferTarget(context, target))
3901 {
3902 context->handleError(Error(GL_INVALID_ENUM));
3903 return false;
3904 }
3905
3906 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3907
3908 if (!buffer)
3909 {
3910 context->handleError(Error(GL_INVALID_OPERATION));
3911 return false;
3912 }
3913
3914 if (buffer->isMapped())
3915 {
3916 context->handleError(Error(GL_INVALID_OPERATION));
3917 return false;
3918 }
3919
3920 // Check for possible overflow of size + offset
3921 angle::CheckedNumeric<size_t> checkedSize(size);
3922 checkedSize += offset;
3923 if (!checkedSize.IsValid())
3924 {
3925 context->handleError(Error(GL_OUT_OF_MEMORY));
3926 return false;
3927 }
3928
3929 if (size + offset > buffer->getSize())
3930 {
3931 context->handleError(Error(GL_INVALID_VALUE));
3932 return false;
3933 }
3934
Martin Radev4c4c8e72016-08-04 12:25:34 +03003935 return true;
3936}
3937
Geoff Langc339c4e2016-11-29 10:37:36 -05003938bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003939{
Geoff Langc339c4e2016-11-29 10:37:36 -05003940 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003941 {
3942 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003943 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003944 return false;
3945 }
3946
3947 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3948 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003949 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003950 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003951 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003952 return false;
3953 }
3954
3955 return true;
3956}
3957
Jamie Madillef300b12016-10-07 15:12:09 -04003958bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3959{
3960 if (texture < GL_TEXTURE0 ||
3961 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3962 {
3963 context->handleError(Error(GL_INVALID_ENUM));
3964 return false;
3965 }
3966
3967 return true;
3968}
3969
3970bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3971{
3972 Program *programObject = GetValidProgram(context, program);
3973 if (!programObject)
3974 {
3975 return false;
3976 }
3977
3978 Shader *shaderObject = GetValidShader(context, shader);
3979 if (!shaderObject)
3980 {
3981 return false;
3982 }
3983
3984 switch (shaderObject->getType())
3985 {
3986 case GL_VERTEX_SHADER:
3987 {
3988 if (programObject->getAttachedVertexShader())
3989 {
3990 context->handleError(Error(GL_INVALID_OPERATION));
3991 return false;
3992 }
3993 break;
3994 }
3995 case GL_FRAGMENT_SHADER:
3996 {
3997 if (programObject->getAttachedFragmentShader())
3998 {
3999 context->handleError(Error(GL_INVALID_OPERATION));
4000 return false;
4001 }
4002 break;
4003 }
4004 case GL_COMPUTE_SHADER:
4005 {
4006 if (programObject->getAttachedComputeShader())
4007 {
4008 context->handleError(Error(GL_INVALID_OPERATION));
4009 return false;
4010 }
4011 break;
4012 }
4013 default:
4014 UNREACHABLE();
4015 break;
4016 }
4017
4018 return true;
4019}
4020
Jamie Madill01a80ee2016-11-07 12:06:18 -05004021bool ValidateBindAttribLocation(ValidationContext *context,
4022 GLuint program,
4023 GLuint index,
4024 const GLchar *name)
4025{
4026 if (index >= MAX_VERTEX_ATTRIBS)
4027 {
4028 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
4029 return false;
4030 }
4031
4032 if (strncmp(name, "gl_", 3) == 0)
4033 {
4034 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
4035 return false;
4036 }
4037
Geoff Langfc32e8b2017-05-31 14:16:59 -04004038 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4039 // shader-related entry points
4040 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4041 {
4042 context->handleError(Error(GL_INVALID_VALUE, "Attribute name contains invalid characters"));
4043 return false;
4044 }
4045
Jamie Madill01a80ee2016-11-07 12:06:18 -05004046 return GetValidProgram(context, program) != nullptr;
4047}
4048
4049bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4050{
4051 if (!ValidBufferTarget(context, target))
4052 {
4053 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
4054 return false;
4055 }
4056
4057 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4058 !context->isBufferGenerated(buffer))
4059 {
4060 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
4061 return false;
4062 }
4063
4064 return true;
4065}
4066
4067bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4068{
4069 if (!ValidFramebufferTarget(target))
4070 {
4071 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4072 return false;
4073 }
4074
4075 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4076 !context->isFramebufferGenerated(framebuffer))
4077 {
4078 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
4079 return false;
4080 }
4081
4082 return true;
4083}
4084
4085bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4086{
4087 if (target != GL_RENDERBUFFER)
4088 {
4089 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
4090 return false;
4091 }
4092
4093 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4094 !context->isRenderbufferGenerated(renderbuffer))
4095 {
4096 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
4097 return false;
4098 }
4099
4100 return true;
4101}
4102
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004103static bool ValidBlendEquationMode(GLenum mode)
4104{
4105 switch (mode)
4106 {
4107 case GL_FUNC_ADD:
4108 case GL_FUNC_SUBTRACT:
4109 case GL_FUNC_REVERSE_SUBTRACT:
4110 case GL_MIN:
4111 case GL_MAX:
4112 return true;
4113
4114 default:
4115 return false;
4116 }
4117}
4118
Jamie Madillc1d770e2017-04-13 17:31:24 -04004119bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004120 GLfloat red,
4121 GLfloat green,
4122 GLfloat blue,
4123 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004124{
4125 return true;
4126}
4127
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004128bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4129{
4130 if (!ValidBlendEquationMode(mode))
4131 {
4132 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
4133 return false;
4134 }
4135
4136 return true;
4137}
4138
4139bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4140{
4141 if (!ValidBlendEquationMode(modeRGB))
4142 {
4143 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
4144 return false;
4145 }
4146
4147 if (!ValidBlendEquationMode(modeAlpha))
4148 {
4149 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
4150 return false;
4151 }
4152
4153 return true;
4154}
4155
4156bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4157{
4158 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4159}
4160
4161static bool ValidSrcBlendFunc(GLenum srcBlend)
4162{
4163 switch (srcBlend)
4164 {
4165 case GL_ZERO:
4166 case GL_ONE:
4167 case GL_SRC_COLOR:
4168 case GL_ONE_MINUS_SRC_COLOR:
4169 case GL_DST_COLOR:
4170 case GL_ONE_MINUS_DST_COLOR:
4171 case GL_SRC_ALPHA:
4172 case GL_ONE_MINUS_SRC_ALPHA:
4173 case GL_DST_ALPHA:
4174 case GL_ONE_MINUS_DST_ALPHA:
4175 case GL_CONSTANT_COLOR:
4176 case GL_ONE_MINUS_CONSTANT_COLOR:
4177 case GL_CONSTANT_ALPHA:
4178 case GL_ONE_MINUS_CONSTANT_ALPHA:
4179 case GL_SRC_ALPHA_SATURATE:
4180 return true;
4181
4182 default:
4183 return false;
4184 }
4185}
4186
4187static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4188{
4189 switch (dstBlend)
4190 {
4191 case GL_ZERO:
4192 case GL_ONE:
4193 case GL_SRC_COLOR:
4194 case GL_ONE_MINUS_SRC_COLOR:
4195 case GL_DST_COLOR:
4196 case GL_ONE_MINUS_DST_COLOR:
4197 case GL_SRC_ALPHA:
4198 case GL_ONE_MINUS_SRC_ALPHA:
4199 case GL_DST_ALPHA:
4200 case GL_ONE_MINUS_DST_ALPHA:
4201 case GL_CONSTANT_COLOR:
4202 case GL_ONE_MINUS_CONSTANT_COLOR:
4203 case GL_CONSTANT_ALPHA:
4204 case GL_ONE_MINUS_CONSTANT_ALPHA:
4205 return true;
4206
4207 case GL_SRC_ALPHA_SATURATE:
4208 return (contextMajorVersion >= 3);
4209
4210 default:
4211 return false;
4212 }
4213}
4214
4215bool ValidateBlendFuncSeparate(ValidationContext *context,
4216 GLenum srcRGB,
4217 GLenum dstRGB,
4218 GLenum srcAlpha,
4219 GLenum dstAlpha)
4220{
4221 if (!ValidSrcBlendFunc(srcRGB))
4222 {
4223 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4224 return false;
4225 }
4226
4227 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4228 {
4229 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4230 return false;
4231 }
4232
4233 if (!ValidSrcBlendFunc(srcAlpha))
4234 {
4235 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4236 return false;
4237 }
4238
4239 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4240 {
4241 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4242 return false;
4243 }
4244
Frank Henigman146e8a12017-03-02 23:22:37 -05004245 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4246 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004247 {
4248 bool constantColorUsed =
4249 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4250 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4251
4252 bool constantAlphaUsed =
4253 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4254 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4255
4256 if (constantColorUsed && constantAlphaUsed)
4257 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004258 const char *msg;
4259 if (context->getExtensions().webglCompatibility)
4260 {
4261 msg =
4262 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4263 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4264 }
4265 else
4266 {
4267 msg =
4268 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4269 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4270 "implementation.";
4271 ERR() << msg;
4272 }
4273 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004274 return false;
4275 }
4276 }
4277
4278 return true;
4279}
4280
Geoff Langc339c4e2016-11-29 10:37:36 -05004281bool ValidateGetString(Context *context, GLenum name)
4282{
4283 switch (name)
4284 {
4285 case GL_VENDOR:
4286 case GL_RENDERER:
4287 case GL_VERSION:
4288 case GL_SHADING_LANGUAGE_VERSION:
4289 case GL_EXTENSIONS:
4290 break;
4291
4292 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4293 if (!context->getExtensions().requestExtension)
4294 {
4295 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4296 return false;
4297 }
4298 break;
4299
4300 default:
4301 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4302 return false;
4303 }
4304
4305 return true;
4306}
4307
Geoff Lang47c48082016-12-07 15:38:13 -05004308bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4309{
4310 if (width <= 0.0f || isNaN(width))
4311 {
4312 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
4313 return false;
4314 }
4315
4316 return true;
4317}
4318
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004319bool ValidateVertexAttribPointer(ValidationContext *context,
4320 GLuint index,
4321 GLint size,
4322 GLenum type,
4323 GLboolean normalized,
4324 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004325 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004326{
Shao80957d92017-02-20 21:25:59 +08004327 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004328 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004329 return false;
4330 }
4331
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004332 if (stride < 0)
4333 {
Shao80957d92017-02-20 21:25:59 +08004334 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004335 return false;
4336 }
4337
Shao80957d92017-02-20 21:25:59 +08004338 const Caps &caps = context->getCaps();
4339 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004340 {
Shao80957d92017-02-20 21:25:59 +08004341 if (stride > caps.maxVertexAttribStride)
4342 {
4343 context->handleError(
4344 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
4345 return false;
4346 }
4347
4348 if (index >= caps.maxVertexAttribBindings)
4349 {
4350 context->handleError(
4351 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
4352 return false;
4353 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004354 }
4355
4356 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4357 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4358 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4359 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004360 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4361 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004362 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004363 {
4364 context->handleError(
4365 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08004366 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004367 return false;
4368 }
4369
4370 if (context->getExtensions().webglCompatibility)
4371 {
4372 // WebGL 1.0 [Section 6.14] Fixed point support
4373 // The WebGL API does not support the GL_FIXED data type.
4374 if (type == GL_FIXED)
4375 {
4376 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4377 return false;
4378 }
4379
Geoff Lang2d62ab72017-03-23 16:54:40 -04004380 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004381 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004382 return false;
4383 }
4384 }
4385
4386 return true;
4387}
4388
Jamie Madill876429b2017-04-20 15:46:24 -04004389bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004390{
4391 if (context->getExtensions().webglCompatibility && zNear > zFar)
4392 {
4393 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4394 return false;
4395 }
4396
4397 return true;
4398}
4399
Jamie Madille8fb6402017-02-14 17:56:40 -05004400bool ValidateRenderbufferStorage(ValidationContext *context,
4401 GLenum target,
4402 GLenum internalformat,
4403 GLsizei width,
4404 GLsizei height)
4405{
4406 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4407 height);
4408}
4409
4410bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4411 GLenum target,
4412 GLsizei samples,
4413 GLenum internalformat,
4414 GLsizei width,
4415 GLsizei height)
4416{
4417 if (!context->getExtensions().framebufferMultisample)
4418 {
4419 context->handleError(
4420 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4421 return false;
4422 }
4423
4424 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4425 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4426 // generated.
4427 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4428 {
4429 context->handleError(Error(GL_INVALID_VALUE));
4430 return false;
4431 }
4432
4433 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4434 // the specified storage. This is different than ES 3.0 in which a sample number higher
4435 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4436 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4437 if (context->getClientMajorVersion() >= 3)
4438 {
4439 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4440 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4441 {
4442 context->handleError(Error(GL_OUT_OF_MEMORY));
4443 return false;
4444 }
4445 }
4446
4447 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4448 width, height);
4449}
4450
Jamie Madillc1d770e2017-04-13 17:31:24 -04004451bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4452{
4453 if (!ValidFramebufferTarget(target))
4454 {
4455 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4456 return false;
4457 }
4458
4459 return true;
4460}
4461
4462bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004463 GLfloat red,
4464 GLfloat green,
4465 GLfloat blue,
4466 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004467{
4468 return true;
4469}
4470
Jamie Madill876429b2017-04-20 15:46:24 -04004471bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004472{
4473 return true;
4474}
4475
4476bool ValidateClearStencil(ValidationContext *context, GLint s)
4477{
4478 return true;
4479}
4480
4481bool ValidateColorMask(ValidationContext *context,
4482 GLboolean red,
4483 GLboolean green,
4484 GLboolean blue,
4485 GLboolean alpha)
4486{
4487 return true;
4488}
4489
4490bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4491{
4492 return true;
4493}
4494
4495bool ValidateCreateProgram(ValidationContext *context)
4496{
4497 return true;
4498}
4499
4500bool ValidateCullFace(ValidationContext *context, GLenum mode)
4501{
4502 switch (mode)
4503 {
4504 case GL_FRONT:
4505 case GL_BACK:
4506 case GL_FRONT_AND_BACK:
4507 break;
4508
4509 default:
4510 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
4511 return false;
4512 }
4513
4514 return true;
4515}
4516
4517bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4518{
4519 if (program == 0)
4520 {
4521 return false;
4522 }
4523
4524 if (!context->getProgram(program))
4525 {
4526 if (context->getShader(program))
4527 {
4528 context->handleError(
4529 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
4530 return false;
4531 }
4532 else
4533 {
4534 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
4535 return false;
4536 }
4537 }
4538
4539 return true;
4540}
4541
4542bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4543{
4544 if (shader == 0)
4545 {
4546 return false;
4547 }
4548
4549 if (!context->getShader(shader))
4550 {
4551 if (context->getProgram(shader))
4552 {
4553 context->handleError(
4554 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
4555 return false;
4556 }
4557 else
4558 {
4559 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4560 return false;
4561 }
4562 }
4563
4564 return true;
4565}
4566
4567bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4568{
4569 switch (func)
4570 {
4571 case GL_NEVER:
4572 case GL_ALWAYS:
4573 case GL_LESS:
4574 case GL_LEQUAL:
4575 case GL_EQUAL:
4576 case GL_GREATER:
4577 case GL_GEQUAL:
4578 case GL_NOTEQUAL:
4579 break;
4580
4581 default:
4582 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4583 return false;
4584 }
4585
4586 return true;
4587}
4588
4589bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4590{
4591 return true;
4592}
4593
4594bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4595{
4596 Program *programObject = GetValidProgram(context, program);
4597 if (!programObject)
4598 {
4599 return false;
4600 }
4601
4602 Shader *shaderObject = GetValidShader(context, shader);
4603 if (!shaderObject)
4604 {
4605 return false;
4606 }
4607
4608 const Shader *attachedShader = nullptr;
4609
4610 switch (shaderObject->getType())
4611 {
4612 case GL_VERTEX_SHADER:
4613 {
4614 attachedShader = programObject->getAttachedVertexShader();
4615 break;
4616 }
4617 case GL_FRAGMENT_SHADER:
4618 {
4619 attachedShader = programObject->getAttachedFragmentShader();
4620 break;
4621 }
4622 case GL_COMPUTE_SHADER:
4623 {
4624 attachedShader = programObject->getAttachedComputeShader();
4625 break;
4626 }
4627 default:
4628 UNREACHABLE();
4629 return false;
4630 }
4631
4632 if (attachedShader != shaderObject)
4633 {
4634 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4635 return false;
4636 }
4637
4638 return true;
4639}
4640
4641bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4642{
4643 if (index >= MAX_VERTEX_ATTRIBS)
4644 {
4645 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4646 return false;
4647 }
4648
4649 return true;
4650}
4651
4652bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4653{
4654 if (index >= MAX_VERTEX_ATTRIBS)
4655 {
4656 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4657 return false;
4658 }
4659
4660 return true;
4661}
4662
4663bool ValidateFinish(ValidationContext *context)
4664{
4665 return true;
4666}
4667
4668bool ValidateFlush(ValidationContext *context)
4669{
4670 return true;
4671}
4672
4673bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4674{
4675 switch (mode)
4676 {
4677 case GL_CW:
4678 case GL_CCW:
4679 break;
4680 default:
4681 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4682 return false;
4683 }
4684
4685 return true;
4686}
4687
4688bool ValidateGetActiveAttrib(ValidationContext *context,
4689 GLuint program,
4690 GLuint index,
4691 GLsizei bufsize,
4692 GLsizei *length,
4693 GLint *size,
4694 GLenum *type,
4695 GLchar *name)
4696{
4697 if (bufsize < 0)
4698 {
4699 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4700 return false;
4701 }
4702
4703 Program *programObject = GetValidProgram(context, program);
4704
4705 if (!programObject)
4706 {
4707 return false;
4708 }
4709
4710 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4711 {
4712 context->handleError(
4713 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4714 return false;
4715 }
4716
4717 return true;
4718}
4719
4720bool ValidateGetActiveUniform(ValidationContext *context,
4721 GLuint program,
4722 GLuint index,
4723 GLsizei bufsize,
4724 GLsizei *length,
4725 GLint *size,
4726 GLenum *type,
4727 GLchar *name)
4728{
4729 if (bufsize < 0)
4730 {
4731 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4732 return false;
4733 }
4734
4735 Program *programObject = GetValidProgram(context, program);
4736
4737 if (!programObject)
4738 {
4739 return false;
4740 }
4741
4742 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4743 {
4744 context->handleError(
4745 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4746 return false;
4747 }
4748
4749 return true;
4750}
4751
4752bool ValidateGetAttachedShaders(ValidationContext *context,
4753 GLuint program,
4754 GLsizei maxcount,
4755 GLsizei *count,
4756 GLuint *shaders)
4757{
4758 if (maxcount < 0)
4759 {
4760 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4761 return false;
4762 }
4763
4764 Program *programObject = GetValidProgram(context, program);
4765
4766 if (!programObject)
4767 {
4768 return false;
4769 }
4770
4771 return true;
4772}
4773
4774bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4775{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004776 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4777 // shader-related entry points
4778 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4779 {
4780 context->handleError(Error(GL_INVALID_VALUE, "Attribute name contains invalid characters"));
4781 return false;
4782 }
4783
Jamie Madillc1d770e2017-04-13 17:31:24 -04004784 Program *programObject = GetValidProgram(context, program);
4785
4786 if (!programObject)
4787 {
4788 return false;
4789 }
4790
4791 if (!programObject->isLinked())
4792 {
4793 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4794 return false;
4795 }
4796
4797 return true;
4798}
4799
4800bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4801{
4802 GLenum nativeType;
4803 unsigned int numParams = 0;
4804 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4805}
4806
4807bool ValidateGetError(ValidationContext *context)
4808{
4809 return true;
4810}
4811
4812bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4813{
4814 GLenum nativeType;
4815 unsigned int numParams = 0;
4816 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4817}
4818
4819bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4820{
4821 GLenum nativeType;
4822 unsigned int numParams = 0;
4823 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4824}
4825
4826bool ValidateGetProgramInfoLog(ValidationContext *context,
4827 GLuint program,
4828 GLsizei bufsize,
4829 GLsizei *length,
4830 GLchar *infolog)
4831{
4832 if (bufsize < 0)
4833 {
4834 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4835 return false;
4836 }
4837
4838 Program *programObject = GetValidProgram(context, program);
4839 if (!programObject)
4840 {
4841 return false;
4842 }
4843
4844 return true;
4845}
4846
4847bool ValidateGetShaderInfoLog(ValidationContext *context,
4848 GLuint shader,
4849 GLsizei bufsize,
4850 GLsizei *length,
4851 GLchar *infolog)
4852{
4853 if (bufsize < 0)
4854 {
4855 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4856 return false;
4857 }
4858
4859 Shader *shaderObject = GetValidShader(context, shader);
4860 if (!shaderObject)
4861 {
4862 return false;
4863 }
4864
4865 return true;
4866}
4867
4868bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4869 GLenum shadertype,
4870 GLenum precisiontype,
4871 GLint *range,
4872 GLint *precision)
4873{
4874 switch (shadertype)
4875 {
4876 case GL_VERTEX_SHADER:
4877 case GL_FRAGMENT_SHADER:
4878 break;
4879 case GL_COMPUTE_SHADER:
4880 context->handleError(
4881 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4882 return false;
4883 default:
4884 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4885 return false;
4886 }
4887
4888 switch (precisiontype)
4889 {
4890 case GL_LOW_FLOAT:
4891 case GL_MEDIUM_FLOAT:
4892 case GL_HIGH_FLOAT:
4893 case GL_LOW_INT:
4894 case GL_MEDIUM_INT:
4895 case GL_HIGH_INT:
4896 break;
4897
4898 default:
4899 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4900 return false;
4901 }
4902
4903 return true;
4904}
4905
4906bool ValidateGetShaderSource(ValidationContext *context,
4907 GLuint shader,
4908 GLsizei bufsize,
4909 GLsizei *length,
4910 GLchar *source)
4911{
4912 if (bufsize < 0)
4913 {
4914 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4915 return false;
4916 }
4917
4918 Shader *shaderObject = GetValidShader(context, shader);
4919 if (!shaderObject)
4920 {
4921 return false;
4922 }
4923
4924 return true;
4925}
4926
4927bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4928{
4929 if (strstr(name, "gl_") == name)
4930 {
4931 return false;
4932 }
4933
Geoff Langfc32e8b2017-05-31 14:16:59 -04004934 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4935 // shader-related entry points
4936 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4937 {
4938 context->handleError(Error(GL_INVALID_VALUE, "Uniform name contains invalid characters"));
4939 return false;
4940 }
4941
Jamie Madillc1d770e2017-04-13 17:31:24 -04004942 Program *programObject = GetValidProgram(context, program);
4943
4944 if (!programObject)
4945 {
4946 return false;
4947 }
4948
4949 if (!programObject->isLinked())
4950 {
4951 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4952 return false;
4953 }
4954
4955 return true;
4956}
4957
4958bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4959{
4960 switch (mode)
4961 {
4962 case GL_FASTEST:
4963 case GL_NICEST:
4964 case GL_DONT_CARE:
4965 break;
4966
4967 default:
4968 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4969 return false;
4970 }
4971
4972 switch (target)
4973 {
4974 case GL_GENERATE_MIPMAP_HINT:
4975 break;
4976
4977 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4978 if (!context->getExtensions().standardDerivatives)
4979 {
4980 context->handleError(
4981 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4982 return false;
4983 }
4984 break;
4985
4986 default:
4987 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4988 return false;
4989 }
4990
4991 return true;
4992}
4993
4994bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4995{
4996 return true;
4997}
4998
4999bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5000{
5001 return true;
5002}
5003
5004bool ValidateIsProgram(ValidationContext *context, GLuint program)
5005{
5006 return true;
5007}
5008
5009bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5010{
5011 return true;
5012}
5013
5014bool ValidateIsShader(ValidationContext *context, GLuint shader)
5015{
5016 return true;
5017}
5018
5019bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5020{
5021 return true;
5022}
5023
5024bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5025{
5026 if (context->getClientMajorVersion() < 3)
5027 {
5028 switch (pname)
5029 {
5030 case GL_UNPACK_IMAGE_HEIGHT:
5031 case GL_UNPACK_SKIP_IMAGES:
5032 context->handleError(Error(GL_INVALID_ENUM));
5033 return false;
5034
5035 case GL_UNPACK_ROW_LENGTH:
5036 case GL_UNPACK_SKIP_ROWS:
5037 case GL_UNPACK_SKIP_PIXELS:
5038 if (!context->getExtensions().unpackSubimage)
5039 {
5040 context->handleError(Error(GL_INVALID_ENUM));
5041 return false;
5042 }
5043 break;
5044
5045 case GL_PACK_ROW_LENGTH:
5046 case GL_PACK_SKIP_ROWS:
5047 case GL_PACK_SKIP_PIXELS:
5048 if (!context->getExtensions().packSubimage)
5049 {
5050 context->handleError(Error(GL_INVALID_ENUM));
5051 return false;
5052 }
5053 break;
5054 }
5055 }
5056
5057 if (param < 0)
5058 {
5059 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
5060 return false;
5061 }
5062
5063 switch (pname)
5064 {
5065 case GL_UNPACK_ALIGNMENT:
5066 if (param != 1 && param != 2 && param != 4 && param != 8)
5067 {
5068 context->handleError(Error(GL_INVALID_VALUE));
5069 return false;
5070 }
5071 break;
5072
5073 case GL_PACK_ALIGNMENT:
5074 if (param != 1 && param != 2 && param != 4 && param != 8)
5075 {
5076 context->handleError(Error(GL_INVALID_VALUE));
5077 return false;
5078 }
5079 break;
5080
5081 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5082 case GL_UNPACK_ROW_LENGTH:
5083 case GL_UNPACK_IMAGE_HEIGHT:
5084 case GL_UNPACK_SKIP_IMAGES:
5085 case GL_UNPACK_SKIP_ROWS:
5086 case GL_UNPACK_SKIP_PIXELS:
5087 case GL_PACK_ROW_LENGTH:
5088 case GL_PACK_SKIP_ROWS:
5089 case GL_PACK_SKIP_PIXELS:
5090 break;
5091
5092 default:
5093 context->handleError(Error(GL_INVALID_ENUM));
5094 return false;
5095 }
5096
5097 return true;
5098}
5099
5100bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5101{
5102 return true;
5103}
5104
5105bool ValidateReleaseShaderCompiler(ValidationContext *context)
5106{
5107 return true;
5108}
5109
Jamie Madill876429b2017-04-20 15:46:24 -04005110bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005111{
5112 return true;
5113}
5114
5115bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5116{
5117 if (width < 0 || height < 0)
5118 {
5119 context->handleError(
5120 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
5121 return false;
5122 }
5123
5124 return true;
5125}
5126
5127bool ValidateShaderBinary(ValidationContext *context,
5128 GLsizei n,
5129 const GLuint *shaders,
5130 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005131 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005132 GLsizei length)
5133{
5134 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5135 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5136 shaderBinaryFormats.end())
5137 {
5138 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
5139 return false;
5140 }
5141
5142 return true;
5143}
5144
5145bool ValidateShaderSource(ValidationContext *context,
5146 GLuint shader,
5147 GLsizei count,
5148 const GLchar *const *string,
5149 const GLint *length)
5150{
5151 if (count < 0)
5152 {
5153 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
5154 return false;
5155 }
5156
Geoff Langfc32e8b2017-05-31 14:16:59 -04005157 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5158 // shader-related entry points
5159 if (context->getExtensions().webglCompatibility)
5160 {
5161 for (GLsizei i = 0; i < count; i++)
5162 {
5163 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
5164 if (!IsValidESSLString(string[i], len))
5165 {
5166 context->handleError(
5167 Error(GL_INVALID_VALUE, "Shader source contains invalid characters"));
5168 return false;
5169 }
5170 }
5171 }
5172
Jamie Madillc1d770e2017-04-13 17:31:24 -04005173 Shader *shaderObject = GetValidShader(context, shader);
5174 if (!shaderObject)
5175 {
5176 return false;
5177 }
5178
5179 return true;
5180}
5181
5182bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5183{
5184 if (!IsValidStencilFunc(func))
5185 {
5186 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
5187 return false;
5188 }
5189
5190 return true;
5191}
5192
5193bool ValidateStencilFuncSeparate(ValidationContext *context,
5194 GLenum face,
5195 GLenum func,
5196 GLint ref,
5197 GLuint mask)
5198{
5199 if (!IsValidStencilFace(face))
5200 {
5201 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5202 return false;
5203 }
5204
5205 if (!IsValidStencilFunc(func))
5206 {
5207 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
5208 return false;
5209 }
5210
5211 return true;
5212}
5213
5214bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5215{
5216 return true;
5217}
5218
5219bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5220{
5221 if (!IsValidStencilFace(face))
5222 {
5223 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5224 return false;
5225 }
5226
5227 return true;
5228}
5229
5230bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5231{
5232 if (!IsValidStencilOp(fail))
5233 {
5234 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
5235 return false;
5236 }
5237
5238 if (!IsValidStencilOp(zfail))
5239 {
5240 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
5241 return false;
5242 }
5243
5244 if (!IsValidStencilOp(zpass))
5245 {
5246 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
5247 return false;
5248 }
5249
5250 return true;
5251}
5252
5253bool ValidateStencilOpSeparate(ValidationContext *context,
5254 GLenum face,
5255 GLenum fail,
5256 GLenum zfail,
5257 GLenum zpass)
5258{
5259 if (!IsValidStencilFace(face))
5260 {
5261 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5262 return false;
5263 }
5264
5265 return ValidateStencilOp(context, fail, zfail, zpass);
5266}
5267
5268bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5269{
5270 return ValidateUniform(context, GL_FLOAT, location, 1);
5271}
5272
5273bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5274{
5275 return ValidateUniform(context, GL_FLOAT, location, count);
5276}
5277
Jamie Madillbe849e42017-05-02 15:49:00 -04005278bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5279{
5280 return ValidateUniform1iv(context, location, 1, &x);
5281}
5282
Jamie Madillc1d770e2017-04-13 17:31:24 -04005283bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5284{
5285 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5286}
5287
5288bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5289{
5290 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5291}
5292
5293bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5294{
5295 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5296}
5297
5298bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5299{
5300 return ValidateUniform(context, GL_INT_VEC2, location, count);
5301}
5302
5303bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5304{
5305 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5306}
5307
5308bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5309{
5310 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5311}
5312
5313bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5314{
5315 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5316}
5317
5318bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5319{
5320 return ValidateUniform(context, GL_INT_VEC3, location, count);
5321}
5322
5323bool ValidateUniform4f(ValidationContext *context,
5324 GLint location,
5325 GLfloat x,
5326 GLfloat y,
5327 GLfloat z,
5328 GLfloat w)
5329{
5330 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5331}
5332
5333bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5334{
5335 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5336}
5337
5338bool ValidateUniform4i(ValidationContext *context,
5339 GLint location,
5340 GLint x,
5341 GLint y,
5342 GLint z,
5343 GLint w)
5344{
5345 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5346}
5347
5348bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5349{
5350 return ValidateUniform(context, GL_INT_VEC4, location, count);
5351}
5352
5353bool ValidateUniformMatrix2fv(ValidationContext *context,
5354 GLint location,
5355 GLsizei count,
5356 GLboolean transpose,
5357 const GLfloat *value)
5358{
5359 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5360}
5361
5362bool ValidateUniformMatrix3fv(ValidationContext *context,
5363 GLint location,
5364 GLsizei count,
5365 GLboolean transpose,
5366 const GLfloat *value)
5367{
5368 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5369}
5370
5371bool ValidateUniformMatrix4fv(ValidationContext *context,
5372 GLint location,
5373 GLsizei count,
5374 GLboolean transpose,
5375 const GLfloat *value)
5376{
5377 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5378}
5379
5380bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5381{
5382 Program *programObject = GetValidProgram(context, program);
5383
5384 if (!programObject)
5385 {
5386 return false;
5387 }
5388
5389 return true;
5390}
5391
5392bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5393{
5394 if (index >= MAX_VERTEX_ATTRIBS)
5395 {
5396 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
5397 return false;
5398 }
5399
5400 return true;
5401}
5402
5403bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5404{
5405 return ValidateVertexAttribIndex(context, index);
5406}
5407
5408bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5409{
5410 return ValidateVertexAttribIndex(context, index);
5411}
5412
5413bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5414{
5415 return ValidateVertexAttribIndex(context, index);
5416}
5417
5418bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5419{
5420 return ValidateVertexAttribIndex(context, index);
5421}
5422
5423bool ValidateVertexAttrib3f(ValidationContext *context,
5424 GLuint index,
5425 GLfloat x,
5426 GLfloat y,
5427 GLfloat z)
5428{
5429 return ValidateVertexAttribIndex(context, index);
5430}
5431
5432bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5433{
5434 return ValidateVertexAttribIndex(context, index);
5435}
5436
5437bool ValidateVertexAttrib4f(ValidationContext *context,
5438 GLuint index,
5439 GLfloat x,
5440 GLfloat y,
5441 GLfloat z,
5442 GLfloat w)
5443{
5444 return ValidateVertexAttribIndex(context, index);
5445}
5446
5447bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5448{
5449 return ValidateVertexAttribIndex(context, index);
5450}
5451
5452bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5453{
5454 if (width < 0 || height < 0)
5455 {
5456 context->handleError(
5457 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
5458 return false;
5459 }
5460
5461 return true;
5462}
5463
5464bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5465{
5466 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5467}
5468
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005469bool ValidateDrawElements(ValidationContext *context,
5470 GLenum mode,
5471 GLsizei count,
5472 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005473 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005474{
5475 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5476}
5477
Jamie Madillbe849e42017-05-02 15:49:00 -04005478bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5479 GLenum target,
5480 GLenum attachment,
5481 GLenum pname,
5482 GLint *params)
5483{
5484 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5485 nullptr);
5486}
5487
5488bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5489{
5490 return ValidateGetProgramivBase(context, program, pname, nullptr);
5491}
5492
5493bool ValidateCopyTexImage2D(ValidationContext *context,
5494 GLenum target,
5495 GLint level,
5496 GLenum internalformat,
5497 GLint x,
5498 GLint y,
5499 GLsizei width,
5500 GLsizei height,
5501 GLint border)
5502{
5503 if (context->getClientMajorVersion() < 3)
5504 {
5505 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5506 0, x, y, width, height, border);
5507 }
5508
5509 ASSERT(context->getClientMajorVersion() == 3);
5510 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5511 0, x, y, width, height, border);
5512}
5513
5514bool ValidateCopyTexSubImage2D(Context *context,
5515 GLenum target,
5516 GLint level,
5517 GLint xoffset,
5518 GLint yoffset,
5519 GLint x,
5520 GLint y,
5521 GLsizei width,
5522 GLsizei height)
5523{
5524 if (context->getClientMajorVersion() < 3)
5525 {
5526 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5527 yoffset, x, y, width, height, 0);
5528 }
5529
5530 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5531 yoffset, 0, x, y, width, height, 0);
5532}
5533
5534bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5535{
5536 return ValidateGenOrDelete(context, n);
5537}
5538
5539bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5540{
5541 return ValidateGenOrDelete(context, n);
5542}
5543
5544bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5545{
5546 return ValidateGenOrDelete(context, n);
5547}
5548
5549bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5550{
5551 return ValidateGenOrDelete(context, n);
5552}
5553
5554bool ValidateDisable(Context *context, GLenum cap)
5555{
5556 if (!ValidCap(context, cap, false))
5557 {
5558 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5559 return false;
5560 }
5561
5562 return true;
5563}
5564
5565bool ValidateEnable(Context *context, GLenum cap)
5566{
5567 if (!ValidCap(context, cap, false))
5568 {
5569 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5570 return false;
5571 }
5572
5573 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5574 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5575 {
5576 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5577 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5578
5579 // We also output an error message to the debugger window if tracing is active, so that
5580 // developers can see the error message.
5581 ERR() << errorMessage;
5582 return false;
5583 }
5584
5585 return true;
5586}
5587
5588bool ValidateFramebufferRenderbuffer(Context *context,
5589 GLenum target,
5590 GLenum attachment,
5591 GLenum renderbuffertarget,
5592 GLuint renderbuffer)
5593{
5594 if (!ValidFramebufferTarget(target) ||
5595 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5596 {
5597 context->handleError(Error(GL_INVALID_ENUM));
5598 return false;
5599 }
5600
5601 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5602 renderbuffertarget, renderbuffer);
5603}
5604
5605bool ValidateFramebufferTexture2D(Context *context,
5606 GLenum target,
5607 GLenum attachment,
5608 GLenum textarget,
5609 GLuint texture,
5610 GLint level)
5611{
5612 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5613 // extension
5614 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5615 level != 0)
5616 {
5617 context->handleError(Error(GL_INVALID_VALUE));
5618 return false;
5619 }
5620
5621 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5622 {
5623 return false;
5624 }
5625
5626 if (texture != 0)
5627 {
5628 gl::Texture *tex = context->getTexture(texture);
5629 ASSERT(tex);
5630
5631 const gl::Caps &caps = context->getCaps();
5632
5633 switch (textarget)
5634 {
5635 case GL_TEXTURE_2D:
5636 {
5637 if (level > gl::log2(caps.max2DTextureSize))
5638 {
5639 context->handleError(Error(GL_INVALID_VALUE));
5640 return false;
5641 }
5642 if (tex->getTarget() != GL_TEXTURE_2D)
5643 {
5644 context->handleError(Error(GL_INVALID_OPERATION,
5645 "Textarget must match the texture target type."));
5646 return false;
5647 }
5648 }
5649 break;
5650
5651 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5652 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5653 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5655 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5657 {
5658 if (level > gl::log2(caps.maxCubeMapTextureSize))
5659 {
5660 context->handleError(Error(GL_INVALID_VALUE));
5661 return false;
5662 }
5663 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5664 {
5665 context->handleError(Error(GL_INVALID_OPERATION,
5666 "Textarget must match the texture target type."));
5667 return false;
5668 }
5669 }
5670 break;
5671
5672 case GL_TEXTURE_2D_MULTISAMPLE:
5673 {
5674 if (context->getClientVersion() < ES_3_1)
5675 {
5676 context->handleError(Error(GL_INVALID_OPERATION,
5677 "Texture target requires at least OpenGL ES 3.1."));
5678 return false;
5679 }
5680
5681 if (level != 0)
5682 {
5683 context->handleError(
5684 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
5685 return false;
5686 }
5687 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5688 {
5689 context->handleError(Error(GL_INVALID_OPERATION,
5690 "Textarget must match the texture target type."));
5691 return false;
5692 }
5693 }
5694 break;
5695
5696 default:
5697 context->handleError(Error(GL_INVALID_ENUM));
5698 return false;
5699 }
5700
5701 const Format &format = tex->getFormat(textarget, level);
5702 if (format.info->compressed)
5703 {
5704 context->handleError(Error(GL_INVALID_OPERATION));
5705 return false;
5706 }
5707 }
5708
5709 return true;
5710}
5711
5712bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5713{
5714 return ValidateGenOrDelete(context, n);
5715}
5716
5717bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5718{
5719 return ValidateGenOrDelete(context, n);
5720}
5721
5722bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5723{
5724 return ValidateGenOrDelete(context, n);
5725}
5726
5727bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5728{
5729 return ValidateGenOrDelete(context, n);
5730}
5731
5732bool ValidateGenerateMipmap(Context *context, GLenum target)
5733{
5734 if (!ValidTextureTarget(context, target))
5735 {
5736 context->handleError(Error(GL_INVALID_ENUM));
5737 return false;
5738 }
5739
5740 Texture *texture = context->getTargetTexture(target);
5741
5742 if (texture == nullptr)
5743 {
5744 context->handleError(Error(GL_INVALID_OPERATION));
5745 return false;
5746 }
5747
5748 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5749
5750 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5751 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5752 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5753 {
5754 context->handleError(Error(GL_INVALID_OPERATION));
5755 return false;
5756 }
5757
5758 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5759 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5760 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5761
5762 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5763 // unsized formats or that are color renderable and filterable. Since we do not track if
5764 // the texture was created with sized or unsized format (only sized formats are stored),
5765 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5766 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5767 // textures since they're the only texture format that can be created with unsized formats
5768 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5769 // was the last version to use add them.
5770 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5771 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5772 {
5773 context->handleError(Error(GL_INVALID_OPERATION));
5774 return false;
5775 }
5776
Geoff Lang65ac5b92017-05-01 13:16:30 -04005777 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5778 bool supportsSRGBMipmapGeneration =
5779 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5780 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005781 {
Geoff Lang65ac5b92017-05-01 13:16:30 -04005782 context->handleError(
5783 Error(GL_INVALID_OPERATION, "Mipmap generation of sRGB textures is not allowed."));
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 return false;
5785 }
5786
5787 // Non-power of 2 ES2 check
5788 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5789 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5790 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5791 {
5792 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
5793 context->handleError(Error(GL_INVALID_OPERATION));
5794 return false;
5795 }
5796
5797 // Cube completeness check
5798 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5799 {
5800 context->handleError(Error(GL_INVALID_OPERATION));
5801 return false;
5802 }
5803
5804 return true;
5805}
5806
5807bool ValidateGetBufferParameteriv(ValidationContext *context,
5808 GLenum target,
5809 GLenum pname,
5810 GLint *params)
5811{
5812 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5813}
5814
5815bool ValidateGetRenderbufferParameteriv(Context *context,
5816 GLenum target,
5817 GLenum pname,
5818 GLint *params)
5819{
5820 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5821}
5822
5823bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5824{
5825 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5826}
5827
5828bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5829{
5830 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5831}
5832
5833bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5834{
5835 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5836}
5837
5838bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5839{
5840 return ValidateGetUniformBase(context, program, location);
5841}
5842
5843bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5844{
5845 return ValidateGetUniformBase(context, program, location);
5846}
5847
5848bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5849{
5850 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5851}
5852
5853bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5854{
5855 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5856}
5857
5858bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5859{
5860 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5861}
5862
5863bool ValidateIsEnabled(Context *context, GLenum cap)
5864{
5865 if (!ValidCap(context, cap, true))
5866 {
5867 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5868 return false;
5869 }
5870
5871 return true;
5872}
5873
5874bool ValidateLinkProgram(Context *context, GLuint program)
5875{
5876 if (context->hasActiveTransformFeedback(program))
5877 {
5878 // ES 3.0.4 section 2.15 page 91
5879 context->handleError(Error(GL_INVALID_OPERATION,
5880 "Cannot link program while program is associated with an active "
5881 "transform feedback object."));
5882 return false;
5883 }
5884
5885 Program *programObject = GetValidProgram(context, program);
5886 if (!programObject)
5887 {
5888 return false;
5889 }
5890
5891 return true;
5892}
5893
5894bool ValidateReadPixels(ValidationContext *context,
5895 GLint x,
5896 GLint y,
5897 GLsizei width,
5898 GLsizei height,
5899 GLenum format,
5900 GLenum type,
5901 void *pixels)
5902{
5903 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5904 nullptr, pixels);
5905}
5906
5907bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5908{
5909 return ValidateTexParameterBase(context, target, pname, -1, &param);
5910}
5911
5912bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5913{
5914 return ValidateTexParameterBase(context, target, pname, -1, params);
5915}
5916
5917bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5918{
5919 return ValidateTexParameterBase(context, target, pname, -1, &param);
5920}
5921
5922bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5923{
5924 return ValidateTexParameterBase(context, target, pname, -1, params);
5925}
5926
5927bool ValidateUseProgram(Context *context, GLuint program)
5928{
5929 if (program != 0)
5930 {
5931 Program *programObject = context->getProgram(program);
5932 if (!programObject)
5933 {
5934 // ES 3.1.0 section 7.3 page 72
5935 if (context->getShader(program))
5936 {
5937 context->handleError(
5938 Error(GL_INVALID_OPERATION,
5939 "Attempted to use a single shader instead of a shader program."));
5940 return false;
5941 }
5942 else
5943 {
5944 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
5945 return false;
5946 }
5947 }
5948 if (!programObject->isLinked())
5949 {
5950 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
5951 return false;
5952 }
5953 }
5954 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5955 {
5956 // ES 3.0.4 section 2.15 page 91
5957 context->handleError(
5958 Error(GL_INVALID_OPERATION,
5959 "Cannot change active program while transform feedback is unpaused."));
5960 return false;
5961 }
5962
5963 return true;
5964}
5965
Jamie Madillc29968b2016-01-20 11:17:23 -05005966} // namespace gl