blob: 9bcf646180db7833dc0b8698bf4c4adfd7aec43e [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 Lang6e898aa2017-06-02 11:17:26 -0400846 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
847 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
848 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
849 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
850 // case.
851 bool nonEqualFormatsAllowed =
852 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
853 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
854
855 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400856 {
Jamie Madill437fa652016-05-03 15:13:24 -0400857 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400858 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 }
860
Geoff Langaae65a42014-05-26 12:43:44 -0400861 const gl::Caps &caps = context->getCaps();
862
Geoff Langa9be0dc2014-12-17 12:34:40 -0500863 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400864 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500865 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
866 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400867 {
Jamie Madill437fa652016-05-03 15:13:24 -0400868 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500869 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400870 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500871 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500872 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500873 {
874 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400875 {
Jamie Madill437fa652016-05-03 15:13:24 -0400876 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400879
Geoff Langa9be0dc2014-12-17 12:34:40 -0500880 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
881 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
882 {
Jamie Madill437fa652016-05-03 15:13:24 -0400883 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500884 return false;
885 }
886 }
887 else
888 {
Jamie Madill437fa652016-05-03 15:13:24 -0400889 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400890 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400891 }
892
He Yunchaoced53ae2016-11-29 15:00:51 +0800893 gl::Texture *texture =
894 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400895 if (!texture)
896 {
Jamie Madill437fa652016-05-03 15:13:24 -0400897 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400898 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400899 }
900
Geoff Langa9be0dc2014-12-17 12:34:40 -0500901 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902 {
Geoff Langca271392017-04-05 12:30:00 -0400903 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
904 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500905 {
906 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
907 return false;
908 }
909
Geoff Langa9be0dc2014-12-17 12:34:40 -0500910 if (format != GL_NONE)
911 {
Geoff Langca271392017-04-05 12:30:00 -0400912 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
913 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500914 {
Jamie Madill437fa652016-05-03 15:13:24 -0400915 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500916 return false;
917 }
918 }
919
920 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
921 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
922 {
Jamie Madill437fa652016-05-03 15:13:24 -0400923 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500924 return false;
925 }
926 }
927 else
928 {
Geoff Lang69cce582015-09-17 13:20:36 -0400929 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500930 {
Jamie Madill437fa652016-05-03 15:13:24 -0400931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500932 return false;
933 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 }
935
936 // Verify zero border
937 if (border != 0)
938 {
Jamie Madill437fa652016-05-03 15:13:24 -0400939 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400940 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400941 }
942
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 if (isCompressed)
944 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400945 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400946 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
947 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 switch (actualInternalFormat)
949 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800950 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
951 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
952 if (!context->getExtensions().textureCompressionDXT1)
953 {
954 context->handleError(Error(GL_INVALID_ENUM));
955 return false;
956 }
957 break;
958 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
959 if (!context->getExtensions().textureCompressionDXT1)
960 {
961 context->handleError(Error(GL_INVALID_ENUM));
962 return false;
963 }
964 break;
965 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
966 if (!context->getExtensions().textureCompressionDXT5)
967 {
968 context->handleError(Error(GL_INVALID_ENUM));
969 return false;
970 }
971 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800972 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
973 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
974 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
975 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
976 if (!context->getExtensions().textureCompressionS3TCsRGB)
977 {
978 context->handleError(Error(GL_INVALID_ENUM));
979 return false;
980 }
981 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 case GL_ETC1_RGB8_OES:
983 if (!context->getExtensions().compressedETC1RGB8Texture)
984 {
985 context->handleError(Error(GL_INVALID_ENUM));
986 return false;
987 }
988 break;
989 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800990 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
991 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
992 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
993 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800994 if (!context->getExtensions().lossyETCDecode)
995 {
996 context->handleError(Error(
997 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
998 return false;
999 }
1000 break;
1001 default:
1002 context->handleError(
1003 Error(GL_INVALID_ENUM,
1004 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -04001005 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001006 }
Geoff Lang966c9402017-04-18 12:38:27 -04001007
1008 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001009 {
Geoff Lang966c9402017-04-18 12:38:27 -04001010 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1011 height, texture->getWidth(target, level),
1012 texture->getHeight(target, level)))
1013 {
1014 context->handleError(
1015 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
1016 return false;
1017 }
1018
1019 if (format != actualInternalFormat)
1020 {
1021 context->handleError(Error(
1022 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
1023 return false;
1024 }
1025 }
1026 else
1027 {
1028 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1029 {
1030 context->handleError(
1031 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
1032 return false;
1033 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034 }
1035 }
1036 else
1037 {
1038 // validate <type> by itself (used as secondary key below)
1039 switch (type)
1040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_UNSIGNED_BYTE:
1042 case GL_UNSIGNED_SHORT_5_6_5:
1043 case GL_UNSIGNED_SHORT_4_4_4_4:
1044 case GL_UNSIGNED_SHORT_5_5_5_1:
1045 case GL_UNSIGNED_SHORT:
1046 case GL_UNSIGNED_INT:
1047 case GL_UNSIGNED_INT_24_8_OES:
1048 case GL_HALF_FLOAT_OES:
1049 case GL_FLOAT:
1050 break;
1051 default:
1052 context->handleError(Error(GL_INVALID_ENUM));
1053 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001054 }
1055
1056 // validate <format> + <type> combinations
1057 // - invalid <format> -> sets INVALID_ENUM
1058 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1059 switch (format)
1060 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001061 case GL_ALPHA:
1062 case GL_LUMINANCE:
1063 case GL_LUMINANCE_ALPHA:
1064 switch (type)
1065 {
1066 case GL_UNSIGNED_BYTE:
1067 case GL_FLOAT:
1068 case GL_HALF_FLOAT_OES:
1069 break;
1070 default:
1071 context->handleError(Error(GL_INVALID_OPERATION));
1072 return false;
1073 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 case GL_RED:
1076 case GL_RG:
1077 if (!context->getExtensions().textureRG)
1078 {
1079 context->handleError(Error(GL_INVALID_ENUM));
1080 return false;
1081 }
1082 switch (type)
1083 {
1084 case GL_UNSIGNED_BYTE:
1085 case GL_FLOAT:
1086 case GL_HALF_FLOAT_OES:
1087 break;
1088 default:
1089 context->handleError(Error(GL_INVALID_OPERATION));
1090 return false;
1091 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001093 case GL_RGB:
1094 switch (type)
1095 {
1096 case GL_UNSIGNED_BYTE:
1097 case GL_UNSIGNED_SHORT_5_6_5:
1098 case GL_FLOAT:
1099 case GL_HALF_FLOAT_OES:
1100 break;
1101 default:
1102 context->handleError(Error(GL_INVALID_OPERATION));
1103 return false;
1104 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 case GL_RGBA:
1107 switch (type)
1108 {
1109 case GL_UNSIGNED_BYTE:
1110 case GL_UNSIGNED_SHORT_4_4_4_4:
1111 case GL_UNSIGNED_SHORT_5_5_5_1:
1112 case GL_FLOAT:
1113 case GL_HALF_FLOAT_OES:
1114 break;
1115 default:
1116 context->handleError(Error(GL_INVALID_OPERATION));
1117 return false;
1118 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 case GL_BGRA_EXT:
1121 switch (type)
1122 {
1123 case GL_UNSIGNED_BYTE:
1124 break;
1125 default:
1126 context->handleError(Error(GL_INVALID_OPERATION));
1127 return false;
1128 }
1129 break;
1130 case GL_SRGB_EXT:
1131 case GL_SRGB_ALPHA_EXT:
1132 if (!context->getExtensions().sRGB)
1133 {
1134 context->handleError(Error(GL_INVALID_ENUM));
1135 return false;
1136 }
1137 switch (type)
1138 {
1139 case GL_UNSIGNED_BYTE:
1140 break;
1141 default:
1142 context->handleError(Error(GL_INVALID_OPERATION));
1143 return false;
1144 }
1145 break;
1146 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1147 // handled below
1148 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1149 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1150 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1151 break;
1152 case GL_DEPTH_COMPONENT:
1153 switch (type)
1154 {
1155 case GL_UNSIGNED_SHORT:
1156 case GL_UNSIGNED_INT:
1157 break;
1158 default:
1159 context->handleError(Error(GL_INVALID_OPERATION));
1160 return false;
1161 }
1162 break;
1163 case GL_DEPTH_STENCIL_OES:
1164 switch (type)
1165 {
1166 case GL_UNSIGNED_INT_24_8_OES:
1167 break;
1168 default:
1169 context->handleError(Error(GL_INVALID_OPERATION));
1170 return false;
1171 }
1172 break;
1173 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001174 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001175 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 }
1177
1178 switch (format)
1179 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001180 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1181 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1182 if (context->getExtensions().textureCompressionDXT1)
1183 {
1184 context->handleError(Error(GL_INVALID_OPERATION));
1185 return false;
1186 }
1187 else
1188 {
1189 context->handleError(Error(GL_INVALID_ENUM));
1190 return false;
1191 }
1192 break;
1193 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1194 if (context->getExtensions().textureCompressionDXT3)
1195 {
1196 context->handleError(Error(GL_INVALID_OPERATION));
1197 return false;
1198 }
1199 else
1200 {
1201 context->handleError(Error(GL_INVALID_ENUM));
1202 return false;
1203 }
1204 break;
1205 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1206 if (context->getExtensions().textureCompressionDXT5)
1207 {
1208 context->handleError(Error(GL_INVALID_OPERATION));
1209 return false;
1210 }
1211 else
1212 {
1213 context->handleError(Error(GL_INVALID_ENUM));
1214 return false;
1215 }
1216 break;
1217 case GL_ETC1_RGB8_OES:
1218 if (context->getExtensions().compressedETC1RGB8Texture)
1219 {
1220 context->handleError(Error(GL_INVALID_OPERATION));
1221 return false;
1222 }
1223 else
1224 {
1225 context->handleError(Error(GL_INVALID_ENUM));
1226 return false;
1227 }
1228 break;
1229 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001230 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1231 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1232 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1233 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 if (context->getExtensions().lossyETCDecode)
1235 {
1236 context->handleError(
1237 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -08001238 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +08001239 return false;
1240 }
1241 else
1242 {
1243 context->handleError(Error(
1244 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1245 return false;
1246 }
1247 break;
1248 case GL_DEPTH_COMPONENT:
1249 case GL_DEPTH_STENCIL_OES:
1250 if (!context->getExtensions().depthTextures)
1251 {
1252 context->handleError(Error(GL_INVALID_VALUE));
1253 return false;
1254 }
1255 if (target != GL_TEXTURE_2D)
1256 {
1257 context->handleError(Error(GL_INVALID_OPERATION));
1258 return false;
1259 }
1260 // OES_depth_texture supports loading depth data and multiple levels,
1261 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001262 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001263 {
1264 context->handleError(Error(GL_INVALID_OPERATION));
1265 return false;
1266 }
1267 break;
1268 default:
1269 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
Geoff Lang6e898aa2017-06-02 11:17:26 -04001272 if (!isSubImage)
1273 {
1274 switch (internalformat)
1275 {
1276 case GL_RGBA32F:
1277 if (!context->getExtensions().colorBufferFloatRGBA)
1278 {
1279 context->handleError(Error(GL_INVALID_VALUE,
1280 "Sized GL_RGBA32F internal format requires "
1281 "GL_CHROMIUM_color_buffer_float_rgba"));
1282 return false;
1283 }
1284 if (type != GL_FLOAT)
1285 {
1286 context->handleError(Error(GL_INVALID_OPERATION,
1287 "Invalid internal format/type combination"));
1288 return false;
1289 }
1290 if (format != GL_RGBA)
1291 {
1292 context->handleError(Error(GL_INVALID_OPERATION,
1293 "Invalid internal format/format combination"));
1294 return false;
1295 }
1296 break;
1297
1298 case GL_RGB32F:
1299 if (!context->getExtensions().colorBufferFloatRGB)
1300 {
1301 context->handleError(Error(GL_INVALID_VALUE,
1302 "Sized GL_RGB32F internal format requires "
1303 "GL_CHROMIUM_color_buffer_float_rgb"));
1304 return false;
1305 }
1306 if (type != GL_FLOAT)
1307 {
1308 context->handleError(Error(GL_INVALID_OPERATION,
1309 "Invalid internal format/type combination"));
1310 return false;
1311 }
1312 if (format != GL_RGB)
1313 {
1314 context->handleError(Error(GL_INVALID_OPERATION,
1315 "Invalid internal format/format combination"));
1316 return false;
1317 }
1318 break;
1319
1320 default:
1321 break;
1322 }
1323 }
1324
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 if (type == GL_FLOAT)
1326 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001327 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 {
Jamie Madill437fa652016-05-03 15:13:24 -04001329 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001330 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 }
1332 }
1333 else if (type == GL_HALF_FLOAT_OES)
1334 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001335 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 {
Jamie Madill437fa652016-05-03 15:13:24 -04001337 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 }
1340 }
1341 }
1342
Geoff Langff5b2d52016-09-07 11:32:23 -04001343 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
1344 imageSize))
1345 {
1346 return false;
1347 }
1348
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 return true;
1350}
1351
He Yunchaoced53ae2016-11-29 15:00:51 +08001352bool ValidateES2TexStorageParameters(Context *context,
1353 GLenum target,
1354 GLsizei levels,
1355 GLenum internalformat,
1356 GLsizei width,
1357 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358{
1359 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1360 {
Jamie Madill437fa652016-05-03 15:13:24 -04001361 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
1365 if (width < 1 || height < 1 || levels < 1)
1366 {
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
1371 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 }
1376
1377 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1378 {
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 }
1382
Geoff Langca271392017-04-05 12:30:00 -04001383 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001384 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 {
Jamie Madill437fa652016-05-03 15:13:24 -04001386 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001387 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
1389
Geoff Langaae65a42014-05-26 12:43:44 -04001390 const gl::Caps &caps = context->getCaps();
1391
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 switch (target)
1393 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001394 case GL_TEXTURE_2D:
1395 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1396 static_cast<GLuint>(height) > caps.max2DTextureSize)
1397 {
1398 context->handleError(Error(GL_INVALID_VALUE));
1399 return false;
1400 }
1401 break;
1402 case GL_TEXTURE_CUBE_MAP:
1403 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1404 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1405 {
1406 context->handleError(Error(GL_INVALID_VALUE));
1407 return false;
1408 }
1409 break;
1410 default:
1411 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001412 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 }
1414
Geoff Langc0b9ef42014-07-02 10:02:37 -04001415 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
1417 if (!gl::isPow2(width) || !gl::isPow2(height))
1418 {
Jamie Madill437fa652016-05-03 15:13:24 -04001419 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001420 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 }
1422 }
1423
1424 switch (internalformat)
1425 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001426 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1427 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1428 if (!context->getExtensions().textureCompressionDXT1)
1429 {
1430 context->handleError(Error(GL_INVALID_ENUM));
1431 return false;
1432 }
1433 break;
1434 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1435 if (!context->getExtensions().textureCompressionDXT3)
1436 {
1437 context->handleError(Error(GL_INVALID_ENUM));
1438 return false;
1439 }
1440 break;
1441 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1442 if (!context->getExtensions().textureCompressionDXT5)
1443 {
1444 context->handleError(Error(GL_INVALID_ENUM));
1445 return false;
1446 }
1447 break;
1448 case GL_ETC1_RGB8_OES:
1449 if (!context->getExtensions().compressedETC1RGB8Texture)
1450 {
1451 context->handleError(Error(GL_INVALID_ENUM));
1452 return false;
1453 }
1454 break;
1455 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001456 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1457 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1458 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1459 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 if (!context->getExtensions().lossyETCDecode)
1461 {
1462 context->handleError(
1463 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1464 return false;
1465 }
1466 break;
1467 case GL_RGBA32F_EXT:
1468 case GL_RGB32F_EXT:
1469 case GL_ALPHA32F_EXT:
1470 case GL_LUMINANCE32F_EXT:
1471 case GL_LUMINANCE_ALPHA32F_EXT:
1472 if (!context->getExtensions().textureFloat)
1473 {
1474 context->handleError(Error(GL_INVALID_ENUM));
1475 return false;
1476 }
1477 break;
1478 case GL_RGBA16F_EXT:
1479 case GL_RGB16F_EXT:
1480 case GL_ALPHA16F_EXT:
1481 case GL_LUMINANCE16F_EXT:
1482 case GL_LUMINANCE_ALPHA16F_EXT:
1483 if (!context->getExtensions().textureHalfFloat)
1484 {
1485 context->handleError(Error(GL_INVALID_ENUM));
1486 return false;
1487 }
1488 break;
1489 case GL_R8_EXT:
1490 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001491 if (!context->getExtensions().textureRG)
1492 {
1493 context->handleError(Error(GL_INVALID_ENUM));
1494 return false;
1495 }
1496 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001497 case GL_R16F_EXT:
1498 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001499 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1500 {
1501 context->handleError(Error(GL_INVALID_ENUM));
1502 return false;
1503 }
1504 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001505 case GL_R32F_EXT:
1506 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001507 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001508 {
1509 context->handleError(Error(GL_INVALID_ENUM));
1510 return false;
1511 }
1512 break;
1513 case GL_DEPTH_COMPONENT16:
1514 case GL_DEPTH_COMPONENT32_OES:
1515 case GL_DEPTH24_STENCIL8_OES:
1516 if (!context->getExtensions().depthTextures)
1517 {
1518 context->handleError(Error(GL_INVALID_ENUM));
1519 return false;
1520 }
1521 if (target != GL_TEXTURE_2D)
1522 {
1523 context->handleError(Error(GL_INVALID_OPERATION));
1524 return false;
1525 }
1526 // ANGLE_depth_texture only supports 1-level textures
1527 if (levels != 1)
1528 {
1529 context->handleError(Error(GL_INVALID_OPERATION));
1530 return false;
1531 }
1532 break;
1533 default:
1534 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 }
1536
Geoff Lang691e58c2014-12-19 17:03:25 -05001537 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 if (!texture || texture->id() == 0)
1539 {
Jamie Madill437fa652016-05-03 15:13:24 -04001540 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001541 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001542 }
1543
Geoff Lang69cce582015-09-17 13:20:36 -04001544 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001545 {
Jamie Madill437fa652016-05-03 15:13:24 -04001546 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001547 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001548 }
1549
1550 return true;
1551}
1552
He Yunchaoced53ae2016-11-29 15:00:51 +08001553bool ValidateDiscardFramebufferEXT(Context *context,
1554 GLenum target,
1555 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001556 const GLenum *attachments)
1557{
Jamie Madillc29968b2016-01-20 11:17:23 -05001558 if (!context->getExtensions().discardFramebuffer)
1559 {
Jamie Madill437fa652016-05-03 15:13:24 -04001560 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001561 return false;
1562 }
1563
Austin Kinross08332632015-05-05 13:35:47 -07001564 bool defaultFramebuffer = false;
1565
1566 switch (target)
1567 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001568 case GL_FRAMEBUFFER:
1569 defaultFramebuffer =
1570 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1571 break;
1572 default:
1573 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1574 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001575 }
1576
He Yunchaoced53ae2016-11-29 15:00:51 +08001577 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1578 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001579}
1580
Austin Kinrossbc781f32015-10-26 09:27:38 -07001581bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1582{
1583 if (!context->getExtensions().vertexArrayObject)
1584 {
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001586 return false;
1587 }
1588
1589 return ValidateBindVertexArrayBase(context, array);
1590}
1591
1592bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1593{
1594 if (!context->getExtensions().vertexArrayObject)
1595 {
Jamie Madill437fa652016-05-03 15:13:24 -04001596 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001597 return false;
1598 }
1599
Olli Etuaho41997e72016-03-10 13:38:39 +02001600 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001601}
1602
1603bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1604{
1605 if (!context->getExtensions().vertexArrayObject)
1606 {
Jamie Madill437fa652016-05-03 15:13:24 -04001607 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001608 return false;
1609 }
1610
Olli Etuaho41997e72016-03-10 13:38:39 +02001611 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001612}
1613
1614bool ValidateIsVertexArrayOES(Context *context)
1615{
1616 if (!context->getExtensions().vertexArrayObject)
1617 {
Jamie Madill437fa652016-05-03 15:13:24 -04001618 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001619 return false;
1620 }
1621
1622 return true;
1623}
Geoff Langc5629752015-12-07 16:29:04 -05001624
1625bool ValidateProgramBinaryOES(Context *context,
1626 GLuint program,
1627 GLenum binaryFormat,
1628 const void *binary,
1629 GLint length)
1630{
1631 if (!context->getExtensions().getProgramBinary)
1632 {
Jamie Madill437fa652016-05-03 15:13:24 -04001633 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001634 return false;
1635 }
1636
1637 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1638}
1639
1640bool ValidateGetProgramBinaryOES(Context *context,
1641 GLuint program,
1642 GLsizei bufSize,
1643 GLsizei *length,
1644 GLenum *binaryFormat,
1645 void *binary)
1646{
1647 if (!context->getExtensions().getProgramBinary)
1648 {
Jamie Madill437fa652016-05-03 15:13:24 -04001649 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001650 return false;
1651 }
1652
1653 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1654}
Geoff Lange102fee2015-12-10 11:23:30 -05001655
Geoff Lang70d0f492015-12-10 17:45:46 -05001656static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1657{
1658 switch (source)
1659 {
1660 case GL_DEBUG_SOURCE_API:
1661 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1662 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1663 case GL_DEBUG_SOURCE_OTHER:
1664 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1665 return !mustBeThirdPartyOrApplication;
1666
1667 case GL_DEBUG_SOURCE_THIRD_PARTY:
1668 case GL_DEBUG_SOURCE_APPLICATION:
1669 return true;
1670
1671 default:
1672 return false;
1673 }
1674}
1675
1676static bool ValidDebugType(GLenum type)
1677{
1678 switch (type)
1679 {
1680 case GL_DEBUG_TYPE_ERROR:
1681 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1682 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1683 case GL_DEBUG_TYPE_PERFORMANCE:
1684 case GL_DEBUG_TYPE_PORTABILITY:
1685 case GL_DEBUG_TYPE_OTHER:
1686 case GL_DEBUG_TYPE_MARKER:
1687 case GL_DEBUG_TYPE_PUSH_GROUP:
1688 case GL_DEBUG_TYPE_POP_GROUP:
1689 return true;
1690
1691 default:
1692 return false;
1693 }
1694}
1695
1696static bool ValidDebugSeverity(GLenum severity)
1697{
1698 switch (severity)
1699 {
1700 case GL_DEBUG_SEVERITY_HIGH:
1701 case GL_DEBUG_SEVERITY_MEDIUM:
1702 case GL_DEBUG_SEVERITY_LOW:
1703 case GL_DEBUG_SEVERITY_NOTIFICATION:
1704 return true;
1705
1706 default:
1707 return false;
1708 }
1709}
1710
Geoff Lange102fee2015-12-10 11:23:30 -05001711bool ValidateDebugMessageControlKHR(Context *context,
1712 GLenum source,
1713 GLenum type,
1714 GLenum severity,
1715 GLsizei count,
1716 const GLuint *ids,
1717 GLboolean enabled)
1718{
1719 if (!context->getExtensions().debug)
1720 {
Jamie Madill437fa652016-05-03 15:13:24 -04001721 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001722 return false;
1723 }
1724
Geoff Lang70d0f492015-12-10 17:45:46 -05001725 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001728 return false;
1729 }
1730
1731 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1732 {
Jamie Madill437fa652016-05-03 15:13:24 -04001733 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001734 return false;
1735 }
1736
1737 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1738 {
Jamie Madill437fa652016-05-03 15:13:24 -04001739 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001740 return false;
1741 }
1742
1743 if (count > 0)
1744 {
1745 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001748 GL_INVALID_OPERATION,
1749 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1750 return false;
1751 }
1752
1753 if (severity != GL_DONT_CARE)
1754 {
Jamie Madill437fa652016-05-03 15:13:24 -04001755 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001756 Error(GL_INVALID_OPERATION,
1757 "If count is greater than zero, severity must be GL_DONT_CARE."));
1758 return false;
1759 }
1760 }
1761
Geoff Lange102fee2015-12-10 11:23:30 -05001762 return true;
1763}
1764
1765bool ValidateDebugMessageInsertKHR(Context *context,
1766 GLenum source,
1767 GLenum type,
1768 GLuint id,
1769 GLenum severity,
1770 GLsizei length,
1771 const GLchar *buf)
1772{
1773 if (!context->getExtensions().debug)
1774 {
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001776 return false;
1777 }
1778
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001779 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001780 {
1781 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1782 // not generate an error.
1783 return false;
1784 }
1785
1786 if (!ValidDebugSeverity(severity))
1787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001789 return false;
1790 }
1791
1792 if (!ValidDebugType(type))
1793 {
Jamie Madill437fa652016-05-03 15:13:24 -04001794 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001795 return false;
1796 }
1797
1798 if (!ValidDebugSource(source, true))
1799 {
Jamie Madill437fa652016-05-03 15:13:24 -04001800 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001801 return false;
1802 }
1803
1804 size_t messageLength = (length < 0) ? strlen(buf) : length;
1805 if (messageLength > context->getExtensions().maxDebugMessageLength)
1806 {
Jamie Madill437fa652016-05-03 15:13:24 -04001807 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001808 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1809 return false;
1810 }
1811
Geoff Lange102fee2015-12-10 11:23:30 -05001812 return true;
1813}
1814
1815bool ValidateDebugMessageCallbackKHR(Context *context,
1816 GLDEBUGPROCKHR callback,
1817 const void *userParam)
1818{
1819 if (!context->getExtensions().debug)
1820 {
Jamie Madill437fa652016-05-03 15:13:24 -04001821 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001822 return false;
1823 }
1824
Geoff Lange102fee2015-12-10 11:23:30 -05001825 return true;
1826}
1827
1828bool ValidateGetDebugMessageLogKHR(Context *context,
1829 GLuint count,
1830 GLsizei bufSize,
1831 GLenum *sources,
1832 GLenum *types,
1833 GLuint *ids,
1834 GLenum *severities,
1835 GLsizei *lengths,
1836 GLchar *messageLog)
1837{
1838 if (!context->getExtensions().debug)
1839 {
Jamie Madill437fa652016-05-03 15:13:24 -04001840 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001841 return false;
1842 }
1843
Geoff Lang70d0f492015-12-10 17:45:46 -05001844 if (bufSize < 0 && messageLog != nullptr)
1845 {
Jamie Madill437fa652016-05-03 15:13:24 -04001846 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001847 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1848 return false;
1849 }
1850
Geoff Lange102fee2015-12-10 11:23:30 -05001851 return true;
1852}
1853
1854bool ValidatePushDebugGroupKHR(Context *context,
1855 GLenum source,
1856 GLuint id,
1857 GLsizei length,
1858 const GLchar *message)
1859{
1860 if (!context->getExtensions().debug)
1861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001863 return false;
1864 }
1865
Geoff Lang70d0f492015-12-10 17:45:46 -05001866 if (!ValidDebugSource(source, true))
1867 {
Jamie Madill437fa652016-05-03 15:13:24 -04001868 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001869 return false;
1870 }
1871
1872 size_t messageLength = (length < 0) ? strlen(message) : length;
1873 if (messageLength > context->getExtensions().maxDebugMessageLength)
1874 {
Jamie Madill437fa652016-05-03 15:13:24 -04001875 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001876 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1877 return false;
1878 }
1879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001880 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001881 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1882 {
Jamie Madill437fa652016-05-03 15:13:24 -04001883 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001884 Error(GL_STACK_OVERFLOW,
1885 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1886 return false;
1887 }
1888
Geoff Lange102fee2015-12-10 11:23:30 -05001889 return true;
1890}
1891
1892bool ValidatePopDebugGroupKHR(Context *context)
1893{
1894 if (!context->getExtensions().debug)
1895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001897 return false;
1898 }
1899
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001900 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001901 if (currentStackSize <= 1)
1902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 return false;
1905 }
1906
1907 return true;
1908}
1909
1910static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1911{
1912 switch (identifier)
1913 {
1914 case GL_BUFFER:
1915 if (context->getBuffer(name) == nullptr)
1916 {
Jamie Madill437fa652016-05-03 15:13:24 -04001917 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001918 return false;
1919 }
1920 return true;
1921
1922 case GL_SHADER:
1923 if (context->getShader(name) == nullptr)
1924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001926 return false;
1927 }
1928 return true;
1929
1930 case GL_PROGRAM:
1931 if (context->getProgram(name) == nullptr)
1932 {
Jamie Madill437fa652016-05-03 15:13:24 -04001933 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001934 return false;
1935 }
1936 return true;
1937
1938 case GL_VERTEX_ARRAY:
1939 if (context->getVertexArray(name) == nullptr)
1940 {
Jamie Madill437fa652016-05-03 15:13:24 -04001941 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001942 return false;
1943 }
1944 return true;
1945
1946 case GL_QUERY:
1947 if (context->getQuery(name) == nullptr)
1948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001950 return false;
1951 }
1952 return true;
1953
1954 case GL_TRANSFORM_FEEDBACK:
1955 if (context->getTransformFeedback(name) == nullptr)
1956 {
Jamie Madill437fa652016-05-03 15:13:24 -04001957 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001958 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1959 return false;
1960 }
1961 return true;
1962
1963 case GL_SAMPLER:
1964 if (context->getSampler(name) == nullptr)
1965 {
Jamie Madill437fa652016-05-03 15:13:24 -04001966 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001967 return false;
1968 }
1969 return true;
1970
1971 case GL_TEXTURE:
1972 if (context->getTexture(name) == nullptr)
1973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001975 return false;
1976 }
1977 return true;
1978
1979 case GL_RENDERBUFFER:
1980 if (context->getRenderbuffer(name) == nullptr)
1981 {
Jamie Madill437fa652016-05-03 15:13:24 -04001982 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001983 return false;
1984 }
1985 return true;
1986
1987 case GL_FRAMEBUFFER:
1988 if (context->getFramebuffer(name) == nullptr)
1989 {
Jamie Madill437fa652016-05-03 15:13:24 -04001990 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001991 return false;
1992 }
1993 return true;
1994
1995 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001996 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001997 return false;
1998 }
Geoff Lange102fee2015-12-10 11:23:30 -05001999}
2000
Martin Radev9d901792016-07-15 15:58:58 +03002001static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2002{
2003 size_t labelLength = 0;
2004
2005 if (length < 0)
2006 {
2007 if (label != nullptr)
2008 {
2009 labelLength = strlen(label);
2010 }
2011 }
2012 else
2013 {
2014 labelLength = static_cast<size_t>(length);
2015 }
2016
2017 if (labelLength > context->getExtensions().maxLabelLength)
2018 {
2019 context->handleError(
2020 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
2021 return false;
2022 }
2023
2024 return true;
2025}
2026
Geoff Lange102fee2015-12-10 11:23:30 -05002027bool ValidateObjectLabelKHR(Context *context,
2028 GLenum identifier,
2029 GLuint name,
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 (!ValidateObjectIdentifierAndName(context, identifier, name))
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 ValidateGetObjectLabelKHR(Context *context,
2053 GLenum identifier,
2054 GLuint name,
2055 GLsizei bufSize,
2056 GLsizei *length,
2057 GLchar *label)
2058{
2059 if (!context->getExtensions().debug)
2060 {
Jamie Madill437fa652016-05-03 15:13:24 -04002061 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002062 return false;
2063 }
2064
Geoff Lang70d0f492015-12-10 17:45:46 -05002065 if (bufSize < 0)
2066 {
Jamie Madill437fa652016-05-03 15:13:24 -04002067 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002068 return false;
2069 }
2070
2071 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2072 {
2073 return false;
2074 }
2075
Martin Radev9d901792016-07-15 15:58:58 +03002076 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002077}
2078
2079static bool ValidateObjectPtrName(Context *context, const void *ptr)
2080{
2081 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2082 {
Jamie Madill437fa652016-05-03 15:13:24 -04002083 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002084 return false;
2085 }
2086
Geoff Lange102fee2015-12-10 11:23:30 -05002087 return true;
2088}
2089
2090bool ValidateObjectPtrLabelKHR(Context *context,
2091 const void *ptr,
2092 GLsizei length,
2093 const GLchar *label)
2094{
2095 if (!context->getExtensions().debug)
2096 {
Jamie Madill437fa652016-05-03 15:13:24 -04002097 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002098 return false;
2099 }
2100
Geoff Lang70d0f492015-12-10 17:45:46 -05002101 if (!ValidateObjectPtrName(context, ptr))
2102 {
2103 return false;
2104 }
2105
Martin Radev9d901792016-07-15 15:58:58 +03002106 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002107 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002108 return false;
2109 }
2110
Geoff Lange102fee2015-12-10 11:23:30 -05002111 return true;
2112}
2113
2114bool ValidateGetObjectPtrLabelKHR(Context *context,
2115 const void *ptr,
2116 GLsizei bufSize,
2117 GLsizei *length,
2118 GLchar *label)
2119{
2120 if (!context->getExtensions().debug)
2121 {
Jamie Madill437fa652016-05-03 15:13:24 -04002122 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002123 return false;
2124 }
2125
Geoff Lang70d0f492015-12-10 17:45:46 -05002126 if (bufSize < 0)
2127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002129 return false;
2130 }
2131
2132 if (!ValidateObjectPtrName(context, ptr))
2133 {
2134 return false;
2135 }
2136
Martin Radev9d901792016-07-15 15:58:58 +03002137 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002138}
2139
2140bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2141{
2142 if (!context->getExtensions().debug)
2143 {
Jamie Madill437fa652016-05-03 15:13:24 -04002144 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002145 return false;
2146 }
2147
Geoff Lang70d0f492015-12-10 17:45:46 -05002148 // TODO: represent this in Context::getQueryParameterInfo.
2149 switch (pname)
2150 {
2151 case GL_DEBUG_CALLBACK_FUNCTION:
2152 case GL_DEBUG_CALLBACK_USER_PARAM:
2153 break;
2154
2155 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002157 return false;
2158 }
2159
Geoff Lange102fee2015-12-10 11:23:30 -05002160 return true;
2161}
Jamie Madillc29968b2016-01-20 11:17:23 -05002162
2163bool ValidateBlitFramebufferANGLE(Context *context,
2164 GLint srcX0,
2165 GLint srcY0,
2166 GLint srcX1,
2167 GLint srcY1,
2168 GLint dstX0,
2169 GLint dstY0,
2170 GLint dstX1,
2171 GLint dstY1,
2172 GLbitfield mask,
2173 GLenum filter)
2174{
2175 if (!context->getExtensions().framebufferBlit)
2176 {
Jamie Madill437fa652016-05-03 15:13:24 -04002177 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002178 return false;
2179 }
2180
2181 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2182 {
2183 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04002184 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05002185 GL_INVALID_OPERATION,
2186 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
2187 return false;
2188 }
2189
2190 if (filter == GL_LINEAR)
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002193 return false;
2194 }
2195
Jamie Madill51f40ec2016-06-15 14:06:00 -04002196 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2197 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002198
2199 if (mask & GL_COLOR_BUFFER_BIT)
2200 {
2201 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2202 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2203
2204 if (readColorAttachment && drawColorAttachment)
2205 {
2206 if (!(readColorAttachment->type() == GL_TEXTURE &&
2207 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2208 readColorAttachment->type() != GL_RENDERBUFFER &&
2209 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002212 return false;
2213 }
2214
Geoff Langa15472a2015-08-11 11:48:03 -04002215 for (size_t drawbufferIdx = 0;
2216 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002217 {
Geoff Langa15472a2015-08-11 11:48:03 -04002218 const FramebufferAttachment *attachment =
2219 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2220 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002221 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002222 if (!(attachment->type() == GL_TEXTURE &&
2223 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2224 attachment->type() != GL_RENDERBUFFER &&
2225 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2226 {
Jamie Madill437fa652016-05-03 15:13:24 -04002227 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002228 return false;
2229 }
2230
2231 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002232 if (!Format::SameSized(attachment->getFormat(),
2233 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002234 {
Jamie Madill437fa652016-05-03 15:13:24 -04002235 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002236 return false;
2237 }
2238 }
2239 }
2240
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002241 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002242 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2243 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2244 {
Jamie Madill437fa652016-05-03 15:13:24 -04002245 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002246 return false;
2247 }
2248 }
2249 }
2250
2251 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2252 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2253 for (size_t i = 0; i < 2; i++)
2254 {
2255 if (mask & masks[i])
2256 {
2257 const FramebufferAttachment *readBuffer =
2258 readFramebuffer->getAttachment(attachments[i]);
2259 const FramebufferAttachment *drawBuffer =
2260 drawFramebuffer->getAttachment(attachments[i]);
2261
2262 if (readBuffer && drawBuffer)
2263 {
2264 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2265 dstX0, dstY0, dstX1, dstY1))
2266 {
2267 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05002268 context->handleError(Error(GL_INVALID_OPERATION,
2269 "Only whole-buffer depth and stencil blits are "
2270 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002271 return false;
2272 }
2273
2274 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2275 {
Jamie Madill437fa652016-05-03 15:13:24 -04002276 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002277 return false;
2278 }
2279 }
2280 }
2281 }
2282
2283 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2284 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002285}
Jamie Madillc29968b2016-01-20 11:17:23 -05002286
2287bool ValidateClear(ValidationContext *context, GLbitfield mask)
2288{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002289 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002290 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002293 return false;
2294 }
2295
2296 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2297 {
Jamie Madill437fa652016-05-03 15:13:24 -04002298 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05002299 return false;
2300 }
2301
Geoff Lang76e65652017-03-27 14:58:02 -04002302 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2303 {
2304 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2305 GL_SIGNED_NORMALIZED};
2306
2307 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2308 drawBufferIdx++)
2309 {
2310 if (!ValidateWebGLFramebufferAttachmentClearType(
2311 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2312 {
2313 return false;
2314 }
2315 }
2316 }
2317
Jamie Madillc29968b2016-01-20 11:17:23 -05002318 return true;
2319}
2320
2321bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2322{
2323 if (!context->getExtensions().drawBuffers)
2324 {
Jamie Madill437fa652016-05-03 15:13:24 -04002325 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002326 return false;
2327 }
2328
2329 return ValidateDrawBuffersBase(context, n, bufs);
2330}
2331
Jamie Madill73a84962016-02-12 09:27:23 -05002332bool ValidateTexImage2D(Context *context,
2333 GLenum target,
2334 GLint level,
2335 GLint internalformat,
2336 GLsizei width,
2337 GLsizei height,
2338 GLint border,
2339 GLenum format,
2340 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002341 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002342{
Martin Radev1be913c2016-07-11 17:59:16 +03002343 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002344 {
2345 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002346 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002347 }
2348
Martin Radev1be913c2016-07-11 17:59:16 +03002349 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002350 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002351 0, 0, width, height, 1, border, format, type, -1,
2352 pixels);
2353}
2354
2355bool ValidateTexImage2DRobust(Context *context,
2356 GLenum target,
2357 GLint level,
2358 GLint internalformat,
2359 GLsizei width,
2360 GLsizei height,
2361 GLint border,
2362 GLenum format,
2363 GLenum type,
2364 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002365 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002366{
2367 if (!ValidateRobustEntryPoint(context, bufSize))
2368 {
2369 return false;
2370 }
2371
2372 if (context->getClientMajorVersion() < 3)
2373 {
2374 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2375 0, 0, width, height, border, format, type, bufSize,
2376 pixels);
2377 }
2378
2379 ASSERT(context->getClientMajorVersion() >= 3);
2380 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2381 0, 0, width, height, 1, border, format, type, bufSize,
2382 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002383}
2384
2385bool ValidateTexSubImage2D(Context *context,
2386 GLenum target,
2387 GLint level,
2388 GLint xoffset,
2389 GLint yoffset,
2390 GLsizei width,
2391 GLsizei height,
2392 GLenum format,
2393 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002394 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002395{
2396
Martin Radev1be913c2016-07-11 17:59:16 +03002397 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002398 {
2399 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002400 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002401 }
2402
Martin Radev1be913c2016-07-11 17:59:16 +03002403 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002404 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002405 yoffset, 0, width, height, 1, 0, format, type, -1,
2406 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002407}
2408
Geoff Langc52f6f12016-10-14 10:18:00 -04002409bool ValidateTexSubImage2DRobustANGLE(Context *context,
2410 GLenum target,
2411 GLint level,
2412 GLint xoffset,
2413 GLint yoffset,
2414 GLsizei width,
2415 GLsizei height,
2416 GLenum format,
2417 GLenum type,
2418 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002419 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002420{
2421 if (!ValidateRobustEntryPoint(context, bufSize))
2422 {
2423 return false;
2424 }
2425
2426 if (context->getClientMajorVersion() < 3)
2427 {
2428 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2429 yoffset, width, height, 0, format, type, bufSize,
2430 pixels);
2431 }
2432
2433 ASSERT(context->getClientMajorVersion() >= 3);
2434 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2435 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2436 pixels);
2437}
2438
Jamie Madill73a84962016-02-12 09:27:23 -05002439bool ValidateCompressedTexImage2D(Context *context,
2440 GLenum target,
2441 GLint level,
2442 GLenum internalformat,
2443 GLsizei width,
2444 GLsizei height,
2445 GLint border,
2446 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002447 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002448{
Martin Radev1be913c2016-07-11 17:59:16 +03002449 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002450 {
2451 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002452 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002453 {
2454 return false;
2455 }
2456 }
2457 else
2458 {
Martin Radev1be913c2016-07-11 17:59:16 +03002459 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002460 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002461 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002462 data))
2463 {
2464 return false;
2465 }
2466 }
2467
Geoff Langca271392017-04-05 12:30:00 -04002468 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002469 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002470 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002471 if (blockSizeOrErr.isError())
2472 {
2473 context->handleError(blockSizeOrErr.getError());
2474 return false;
2475 }
2476
2477 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002478 {
Jamie Madill437fa652016-05-03 15:13:24 -04002479 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002480 return false;
2481 }
2482
2483 return true;
2484}
2485
Corentin Wallezb2931602017-04-11 15:58:57 -04002486bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2487 GLenum target,
2488 GLint level,
2489 GLenum internalformat,
2490 GLsizei width,
2491 GLsizei height,
2492 GLint border,
2493 GLsizei imageSize,
2494 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002495 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002496{
2497 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2498 {
2499 return false;
2500 }
2501
2502 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2503 border, imageSize, data);
2504}
2505bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2506 GLenum target,
2507 GLint level,
2508 GLint xoffset,
2509 GLint yoffset,
2510 GLsizei width,
2511 GLsizei height,
2512 GLenum format,
2513 GLsizei imageSize,
2514 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002515 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002516{
2517 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2518 {
2519 return false;
2520 }
2521
2522 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2523 format, imageSize, data);
2524}
2525
Jamie Madill73a84962016-02-12 09:27:23 -05002526bool ValidateCompressedTexSubImage2D(Context *context,
2527 GLenum target,
2528 GLint level,
2529 GLint xoffset,
2530 GLint yoffset,
2531 GLsizei width,
2532 GLsizei height,
2533 GLenum format,
2534 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002535 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002536{
Martin Radev1be913c2016-07-11 17:59:16 +03002537 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002538 {
2539 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002540 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002541 {
2542 return false;
2543 }
2544 }
2545 else
2546 {
Martin Radev1be913c2016-07-11 17:59:16 +03002547 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002548 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002549 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002550 data))
2551 {
2552 return false;
2553 }
2554 }
2555
Geoff Langca271392017-04-05 12:30:00 -04002556 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002557 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002558 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002559 if (blockSizeOrErr.isError())
2560 {
2561 context->handleError(blockSizeOrErr.getError());
2562 return false;
2563 }
2564
2565 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002566 {
Jamie Madill437fa652016-05-03 15:13:24 -04002567 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002568 return false;
2569 }
2570
2571 return true;
2572}
2573
Olli Etuaho4f667482016-03-30 15:56:35 +03002574bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2575{
Geoff Lang496c02d2016-10-20 11:38:11 -07002576 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002577}
2578
2579bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2580{
2581 if (!context->getExtensions().mapBuffer)
2582 {
Jamie Madill437fa652016-05-03 15:13:24 -04002583 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002584 return false;
2585 }
2586
2587 if (!ValidBufferTarget(context, target))
2588 {
Jamie Madill437fa652016-05-03 15:13:24 -04002589 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002590 return false;
2591 }
2592
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002593 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002594
2595 if (buffer == nullptr)
2596 {
Jamie Madill437fa652016-05-03 15:13:24 -04002597 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002598 return false;
2599 }
2600
2601 if (access != GL_WRITE_ONLY_OES)
2602 {
Jamie Madill437fa652016-05-03 15:13:24 -04002603 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002604 return false;
2605 }
2606
2607 if (buffer->isMapped())
2608 {
Jamie Madill437fa652016-05-03 15:13:24 -04002609 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002610 return false;
2611 }
2612
2613 return true;
2614}
2615
2616bool ValidateUnmapBufferOES(Context *context, GLenum target)
2617{
2618 if (!context->getExtensions().mapBuffer)
2619 {
Jamie Madill437fa652016-05-03 15:13:24 -04002620 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002621 return false;
2622 }
2623
2624 return ValidateUnmapBufferBase(context, target);
2625}
2626
2627bool ValidateMapBufferRangeEXT(Context *context,
2628 GLenum target,
2629 GLintptr offset,
2630 GLsizeiptr length,
2631 GLbitfield access)
2632{
2633 if (!context->getExtensions().mapBufferRange)
2634 {
Jamie Madill437fa652016-05-03 15:13:24 -04002635 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002636 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2637 return false;
2638 }
2639
2640 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2641}
2642
2643bool ValidateFlushMappedBufferRangeEXT(Context *context,
2644 GLenum target,
2645 GLintptr offset,
2646 GLsizeiptr length)
2647{
2648 if (!context->getExtensions().mapBufferRange)
2649 {
Jamie Madill437fa652016-05-03 15:13:24 -04002650 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002651 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2652 return false;
2653 }
2654
2655 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2656}
2657
Ian Ewell54f87462016-03-10 13:47:21 -05002658bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2659{
2660 Texture *textureObject = context->getTexture(texture);
2661 if (textureObject && textureObject->getTarget() != target && texture != 0)
2662 {
Jamie Madill437fa652016-05-03 15:13:24 -04002663 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002664 return false;
2665 }
2666
Geoff Langf41a7152016-09-19 15:11:17 -04002667 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2668 !context->isTextureGenerated(texture))
2669 {
2670 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2671 return false;
2672 }
2673
Ian Ewell54f87462016-03-10 13:47:21 -05002674 switch (target)
2675 {
2676 case GL_TEXTURE_2D:
2677 case GL_TEXTURE_CUBE_MAP:
2678 break;
2679
2680 case GL_TEXTURE_3D:
2681 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002682 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002683 {
Jamie Madill437fa652016-05-03 15:13:24 -04002684 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002685 return false;
2686 }
2687 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002688
2689 case GL_TEXTURE_2D_MULTISAMPLE:
2690 if (context->getClientVersion() < Version(3, 1))
2691 {
2692 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2693 return false;
2694 }
Geoff Lang3b573612016-10-31 14:08:10 -04002695 break;
2696
Ian Ewell54f87462016-03-10 13:47:21 -05002697 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002698 if (!context->getExtensions().eglImageExternal &&
2699 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002700 {
Jamie Madill437fa652016-05-03 15:13:24 -04002701 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002702 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2703 return false;
2704 }
2705 break;
2706 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002707 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002708 return false;
2709 }
2710
2711 return true;
2712}
2713
Geoff Langd8605522016-04-13 10:19:12 -04002714bool ValidateBindUniformLocationCHROMIUM(Context *context,
2715 GLuint program,
2716 GLint location,
2717 const GLchar *name)
2718{
2719 if (!context->getExtensions().bindUniformLocation)
2720 {
Jamie Madill437fa652016-05-03 15:13:24 -04002721 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002722 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2723 return false;
2724 }
2725
2726 Program *programObject = GetValidProgram(context, program);
2727 if (!programObject)
2728 {
2729 return false;
2730 }
2731
2732 if (location < 0)
2733 {
Jamie Madill437fa652016-05-03 15:13:24 -04002734 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002735 return false;
2736 }
2737
2738 const Caps &caps = context->getCaps();
2739 if (static_cast<size_t>(location) >=
2740 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2741 {
Jamie Madill437fa652016-05-03 15:13:24 -04002742 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002743 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2744 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2745 return false;
2746 }
2747
Geoff Langfc32e8b2017-05-31 14:16:59 -04002748 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2749 // shader-related entry points
2750 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
2751 {
2752 context->handleError(Error(GL_INVALID_VALUE, "Uniform name contains invalid characters"));
2753 return false;
2754 }
2755
Geoff Langd8605522016-04-13 10:19:12 -04002756 if (strncmp(name, "gl_", 3) == 0)
2757 {
Jamie Madill437fa652016-05-03 15:13:24 -04002758 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002759 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2760 return false;
2761 }
2762
2763 return true;
2764}
2765
Jamie Madille2e406c2016-06-02 13:04:10 -04002766bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002767{
2768 if (!context->getExtensions().framebufferMixedSamples)
2769 {
2770 context->handleError(
2771 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2772 return false;
2773 }
2774 switch (components)
2775 {
2776 case GL_RGB:
2777 case GL_RGBA:
2778 case GL_ALPHA:
2779 case GL_NONE:
2780 break;
2781 default:
2782 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002783 Error(GL_INVALID_ENUM,
2784 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002785 return false;
2786 }
2787
2788 return true;
2789}
2790
Sami Väisänene45e53b2016-05-25 10:36:04 +03002791// CHROMIUM_path_rendering
2792
2793bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2794{
2795 if (!context->getExtensions().pathRendering)
2796 {
2797 context->handleError(
2798 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2799 return false;
2800 }
2801 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2802 {
2803 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2804 return false;
2805 }
2806 if (matrix == nullptr)
2807 {
2808 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2809 return false;
2810 }
2811 return true;
2812}
2813
2814bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2815{
2816 if (!context->getExtensions().pathRendering)
2817 {
2818 context->handleError(
2819 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2820 return false;
2821 }
2822 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2823 {
2824 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2825 return false;
2826 }
2827 return true;
2828}
2829
2830bool ValidateGenPaths(Context *context, GLsizei range)
2831{
2832 if (!context->getExtensions().pathRendering)
2833 {
2834 context->handleError(
2835 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2836 return false;
2837 }
2838
2839 // range = 0 is undefined in NV_path_rendering.
2840 // we add stricter semantic check here and require a non zero positive range.
2841 if (range <= 0)
2842 {
2843 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2844 return false;
2845 }
2846
2847 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2848 {
2849 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2850 return false;
2851 }
2852
2853 return true;
2854}
2855
2856bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2857{
2858 if (!context->getExtensions().pathRendering)
2859 {
2860 context->handleError(
2861 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2862 return false;
2863 }
2864
2865 // range = 0 is undefined in NV_path_rendering.
2866 // we add stricter semantic check here and require a non zero positive range.
2867 if (range <= 0)
2868 {
2869 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2870 return false;
2871 }
2872
2873 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2874 checkedRange += range;
2875
2876 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2877 {
2878 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2879 return false;
2880 }
2881 return true;
2882}
2883
2884bool ValidatePathCommands(Context *context,
2885 GLuint path,
2886 GLsizei numCommands,
2887 const GLubyte *commands,
2888 GLsizei numCoords,
2889 GLenum coordType,
2890 const void *coords)
2891{
2892 if (!context->getExtensions().pathRendering)
2893 {
2894 context->handleError(
2895 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2896 return false;
2897 }
2898 if (!context->hasPath(path))
2899 {
2900 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2901 return false;
2902 }
2903
2904 if (numCommands < 0)
2905 {
2906 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2907 return false;
2908 }
2909 else if (numCommands > 0)
2910 {
2911 if (!commands)
2912 {
2913 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2914 return false;
2915 }
2916 }
2917
2918 if (numCoords < 0)
2919 {
2920 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2921 return false;
2922 }
2923 else if (numCoords > 0)
2924 {
2925 if (!coords)
2926 {
2927 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2928 return false;
2929 }
2930 }
2931
2932 std::uint32_t coordTypeSize = 0;
2933 switch (coordType)
2934 {
2935 case GL_BYTE:
2936 coordTypeSize = sizeof(GLbyte);
2937 break;
2938
2939 case GL_UNSIGNED_BYTE:
2940 coordTypeSize = sizeof(GLubyte);
2941 break;
2942
2943 case GL_SHORT:
2944 coordTypeSize = sizeof(GLshort);
2945 break;
2946
2947 case GL_UNSIGNED_SHORT:
2948 coordTypeSize = sizeof(GLushort);
2949 break;
2950
2951 case GL_FLOAT:
2952 coordTypeSize = sizeof(GLfloat);
2953 break;
2954
2955 default:
2956 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2957 return false;
2958 }
2959
2960 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2961 checkedSize += (coordTypeSize * numCoords);
2962 if (!checkedSize.IsValid())
2963 {
2964 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2965 return false;
2966 }
2967
2968 // early return skips command data validation when it doesn't exist.
2969 if (!commands)
2970 return true;
2971
2972 GLsizei expectedNumCoords = 0;
2973 for (GLsizei i = 0; i < numCommands; ++i)
2974 {
2975 switch (commands[i])
2976 {
2977 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2978 break;
2979 case GL_MOVE_TO_CHROMIUM:
2980 case GL_LINE_TO_CHROMIUM:
2981 expectedNumCoords += 2;
2982 break;
2983 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2984 expectedNumCoords += 4;
2985 break;
2986 case GL_CUBIC_CURVE_TO_CHROMIUM:
2987 expectedNumCoords += 6;
2988 break;
2989 case GL_CONIC_CURVE_TO_CHROMIUM:
2990 expectedNumCoords += 5;
2991 break;
2992 default:
2993 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2994 return false;
2995 }
2996 }
2997 if (expectedNumCoords != numCoords)
2998 {
2999 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
3000 return false;
3001 }
3002
3003 return true;
3004}
3005
3006bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3007{
3008 if (!context->getExtensions().pathRendering)
3009 {
3010 context->handleError(
3011 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3012 return false;
3013 }
3014 if (!context->hasPath(path))
3015 {
3016 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3017 return false;
3018 }
3019
3020 switch (pname)
3021 {
3022 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3023 if (value < 0.0f)
3024 {
3025 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
3026 return false;
3027 }
3028 break;
3029 case GL_PATH_END_CAPS_CHROMIUM:
3030 switch (static_cast<GLenum>(value))
3031 {
3032 case GL_FLAT_CHROMIUM:
3033 case GL_SQUARE_CHROMIUM:
3034 case GL_ROUND_CHROMIUM:
3035 break;
3036 default:
3037 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
3038 return false;
3039 }
3040 break;
3041 case GL_PATH_JOIN_STYLE_CHROMIUM:
3042 switch (static_cast<GLenum>(value))
3043 {
3044 case GL_MITER_REVERT_CHROMIUM:
3045 case GL_BEVEL_CHROMIUM:
3046 case GL_ROUND_CHROMIUM:
3047 break;
3048 default:
3049 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
3050 return false;
3051 }
3052 case GL_PATH_MITER_LIMIT_CHROMIUM:
3053 if (value < 0.0f)
3054 {
3055 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
3056 return false;
3057 }
3058 break;
3059
3060 case GL_PATH_STROKE_BOUND_CHROMIUM:
3061 // no errors, only clamping.
3062 break;
3063
3064 default:
3065 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
3066 return false;
3067 }
3068 return true;
3069}
3070
3071bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3072{
3073 if (!context->getExtensions().pathRendering)
3074 {
3075 context->handleError(
3076 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3077 return false;
3078 }
3079
3080 if (!context->hasPath(path))
3081 {
3082 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3083 return false;
3084 }
3085 if (!value)
3086 {
3087 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
3088 return false;
3089 }
3090
3091 switch (pname)
3092 {
3093 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3094 case GL_PATH_END_CAPS_CHROMIUM:
3095 case GL_PATH_JOIN_STYLE_CHROMIUM:
3096 case GL_PATH_MITER_LIMIT_CHROMIUM:
3097 case GL_PATH_STROKE_BOUND_CHROMIUM:
3098 break;
3099
3100 default:
3101 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
3102 return false;
3103 }
3104
3105 return true;
3106}
3107
3108bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3109{
3110 if (!context->getExtensions().pathRendering)
3111 {
3112 context->handleError(
3113 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3114 return false;
3115 }
3116
3117 switch (func)
3118 {
3119 case GL_NEVER:
3120 case GL_ALWAYS:
3121 case GL_LESS:
3122 case GL_LEQUAL:
3123 case GL_EQUAL:
3124 case GL_GEQUAL:
3125 case GL_GREATER:
3126 case GL_NOTEQUAL:
3127 break;
3128 default:
3129 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
3130 return false;
3131 }
3132
3133 return true;
3134}
3135
3136// Note that the spec specifies that for the path drawing commands
3137// if the path object is not an existing path object the command
3138// does nothing and no error is generated.
3139// However if the path object exists but has not been specified any
3140// commands then an error is generated.
3141
3142bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3143{
3144 if (!context->getExtensions().pathRendering)
3145 {
3146 context->handleError(
3147 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3148 return false;
3149 }
3150 if (context->hasPath(path) && !context->hasPathData(path))
3151 {
3152 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3153 return false;
3154 }
3155
3156 switch (fillMode)
3157 {
3158 case GL_COUNT_UP_CHROMIUM:
3159 case GL_COUNT_DOWN_CHROMIUM:
3160 break;
3161 default:
3162 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3163 return false;
3164 }
3165
3166 if (!isPow2(mask + 1))
3167 {
3168 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3169 return false;
3170 }
3171
3172 return true;
3173}
3174
3175bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3176{
3177 if (!context->getExtensions().pathRendering)
3178 {
3179 context->handleError(
3180 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3181 return false;
3182 }
3183 if (context->hasPath(path) && !context->hasPathData(path))
3184 {
3185 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
3186 return false;
3187 }
3188
3189 return true;
3190}
3191
3192bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3193{
3194 if (!context->getExtensions().pathRendering)
3195 {
3196 context->handleError(
3197 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3198 return false;
3199 }
3200 if (context->hasPath(path) && !context->hasPathData(path))
3201 {
3202 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3203 return false;
3204 }
3205
3206 switch (coverMode)
3207 {
3208 case GL_CONVEX_HULL_CHROMIUM:
3209 case GL_BOUNDING_BOX_CHROMIUM:
3210 break;
3211 default:
3212 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3213 return false;
3214 }
3215 return true;
3216}
3217
3218bool ValidateStencilThenCoverFillPath(Context *context,
3219 GLuint path,
3220 GLenum fillMode,
3221 GLuint mask,
3222 GLenum coverMode)
3223{
3224 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3225 ValidateCoverPath(context, path, coverMode);
3226}
3227
3228bool ValidateStencilThenCoverStrokePath(Context *context,
3229 GLuint path,
3230 GLint reference,
3231 GLuint mask,
3232 GLenum coverMode)
3233{
3234 return ValidateStencilStrokePath(context, path, reference, mask) &&
3235 ValidateCoverPath(context, path, coverMode);
3236}
3237
3238bool ValidateIsPath(Context *context)
3239{
3240 if (!context->getExtensions().pathRendering)
3241 {
3242 context->handleError(
3243 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3244 return false;
3245 }
3246 return true;
3247}
3248
Sami Väisänend59ca052016-06-21 16:10:00 +03003249bool ValidateCoverFillPathInstanced(Context *context,
3250 GLsizei numPaths,
3251 GLenum pathNameType,
3252 const void *paths,
3253 GLuint pathBase,
3254 GLenum coverMode,
3255 GLenum transformType,
3256 const GLfloat *transformValues)
3257{
3258 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3259 transformType, transformValues))
3260 return false;
3261
3262 switch (coverMode)
3263 {
3264 case GL_CONVEX_HULL_CHROMIUM:
3265 case GL_BOUNDING_BOX_CHROMIUM:
3266 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3267 break;
3268 default:
3269 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3270 return false;
3271 }
3272
3273 return true;
3274}
3275
3276bool ValidateCoverStrokePathInstanced(Context *context,
3277 GLsizei numPaths,
3278 GLenum pathNameType,
3279 const void *paths,
3280 GLuint pathBase,
3281 GLenum coverMode,
3282 GLenum transformType,
3283 const GLfloat *transformValues)
3284{
3285 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3286 transformType, transformValues))
3287 return false;
3288
3289 switch (coverMode)
3290 {
3291 case GL_CONVEX_HULL_CHROMIUM:
3292 case GL_BOUNDING_BOX_CHROMIUM:
3293 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3294 break;
3295 default:
3296 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3297 return false;
3298 }
3299
3300 return true;
3301}
3302
3303bool ValidateStencilFillPathInstanced(Context *context,
3304 GLsizei numPaths,
3305 GLenum pathNameType,
3306 const void *paths,
3307 GLuint pathBase,
3308 GLenum fillMode,
3309 GLuint mask,
3310 GLenum transformType,
3311 const GLfloat *transformValues)
3312{
3313
3314 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3315 transformType, transformValues))
3316 return false;
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 return true;
3333}
3334
3335bool ValidateStencilStrokePathInstanced(Context *context,
3336 GLsizei numPaths,
3337 GLenum pathNameType,
3338 const void *paths,
3339 GLuint pathBase,
3340 GLint reference,
3341 GLuint mask,
3342 GLenum transformType,
3343 const GLfloat *transformValues)
3344{
3345 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3346 transformType, transformValues))
3347 return false;
3348
3349 // no more validation here.
3350
3351 return true;
3352}
3353
3354bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3355 GLsizei numPaths,
3356 GLenum pathNameType,
3357 const void *paths,
3358 GLuint pathBase,
3359 GLenum fillMode,
3360 GLuint mask,
3361 GLenum coverMode,
3362 GLenum transformType,
3363 const GLfloat *transformValues)
3364{
3365 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3366 transformType, transformValues))
3367 return false;
3368
3369 switch (coverMode)
3370 {
3371 case GL_CONVEX_HULL_CHROMIUM:
3372 case GL_BOUNDING_BOX_CHROMIUM:
3373 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3374 break;
3375 default:
3376 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3377 return false;
3378 }
3379
3380 switch (fillMode)
3381 {
3382 case GL_COUNT_UP_CHROMIUM:
3383 case GL_COUNT_DOWN_CHROMIUM:
3384 break;
3385 default:
3386 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3387 return false;
3388 }
3389 if (!isPow2(mask + 1))
3390 {
3391 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3392 return false;
3393 }
3394
3395 return true;
3396}
3397
3398bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3399 GLsizei numPaths,
3400 GLenum pathNameType,
3401 const void *paths,
3402 GLuint pathBase,
3403 GLint reference,
3404 GLuint mask,
3405 GLenum coverMode,
3406 GLenum transformType,
3407 const GLfloat *transformValues)
3408{
3409 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3410 transformType, transformValues))
3411 return false;
3412
3413 switch (coverMode)
3414 {
3415 case GL_CONVEX_HULL_CHROMIUM:
3416 case GL_BOUNDING_BOX_CHROMIUM:
3417 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3418 break;
3419 default:
3420 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3421 return false;
3422 }
3423
3424 return true;
3425}
3426
Sami Väisänen46eaa942016-06-29 10:26:37 +03003427bool ValidateBindFragmentInputLocation(Context *context,
3428 GLuint program,
3429 GLint location,
3430 const GLchar *name)
3431{
3432 if (!context->getExtensions().pathRendering)
3433 {
3434 context->handleError(
3435 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3436 return false;
3437 }
3438
3439 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3440 if (location >= MaxLocation)
3441 {
3442 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3443 return false;
3444 }
3445
3446 const auto *programObject = context->getProgram(program);
3447 if (!programObject)
3448 {
3449 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3450 return false;
3451 }
3452
3453 if (!name)
3454 {
3455 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3456 return false;
3457 }
3458
3459 if (angle::BeginsWith(name, "gl_"))
3460 {
3461 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3462 return false;
3463 }
3464
3465 return true;
3466}
3467
3468bool ValidateProgramPathFragmentInputGen(Context *context,
3469 GLuint program,
3470 GLint location,
3471 GLenum genMode,
3472 GLint components,
3473 const GLfloat *coeffs)
3474{
3475 if (!context->getExtensions().pathRendering)
3476 {
3477 context->handleError(
3478 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3479 return false;
3480 }
3481
3482 const auto *programObject = context->getProgram(program);
3483 if (!programObject || programObject->isFlaggedForDeletion())
3484 {
3485 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3486 return false;
3487 }
3488
3489 if (!programObject->isLinked())
3490 {
3491 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3492 return false;
3493 }
3494
3495 switch (genMode)
3496 {
3497 case GL_NONE:
3498 if (components != 0)
3499 {
3500 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3501 return false;
3502 }
3503 break;
3504
3505 case GL_OBJECT_LINEAR_CHROMIUM:
3506 case GL_EYE_LINEAR_CHROMIUM:
3507 case GL_CONSTANT_CHROMIUM:
3508 if (components < 1 || components > 4)
3509 {
3510 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3511 return false;
3512 }
3513 if (!coeffs)
3514 {
3515 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3516 return false;
3517 }
3518 break;
3519
3520 default:
3521 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3522 return false;
3523 }
3524
3525 // If the location is -1 then the command is silently ignored
3526 // and no further validation is needed.
3527 if (location == -1)
3528 return true;
3529
3530 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3531
3532 if (!binding.valid)
3533 {
3534 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3535 return false;
3536 }
3537
3538 if (binding.type != GL_NONE)
3539 {
3540 GLint expectedComponents = 0;
3541 switch (binding.type)
3542 {
3543 case GL_FLOAT:
3544 expectedComponents = 1;
3545 break;
3546 case GL_FLOAT_VEC2:
3547 expectedComponents = 2;
3548 break;
3549 case GL_FLOAT_VEC3:
3550 expectedComponents = 3;
3551 break;
3552 case GL_FLOAT_VEC4:
3553 expectedComponents = 4;
3554 break;
3555 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003556 context->handleError(
3557 Error(GL_INVALID_OPERATION,
3558 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003559 return false;
3560 }
3561 if (expectedComponents != components && genMode != GL_NONE)
3562 {
3563 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3564 return false;
3565 }
3566 }
3567 return true;
3568}
3569
Geoff Lang97073d12016-04-20 10:42:34 -07003570bool ValidateCopyTextureCHROMIUM(Context *context,
3571 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003572 GLint sourceLevel,
3573 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003574 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003575 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003576 GLint internalFormat,
3577 GLenum destType,
3578 GLboolean unpackFlipY,
3579 GLboolean unpackPremultiplyAlpha,
3580 GLboolean unpackUnmultiplyAlpha)
3581{
3582 if (!context->getExtensions().copyTexture)
3583 {
3584 context->handleError(
3585 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3586 return false;
3587 }
3588
Geoff Lang4f0e0032017-05-01 16:04:35 -04003589 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003590 if (source == nullptr)
3591 {
3592 context->handleError(
3593 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3594 return false;
3595 }
3596
3597 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3598 {
3599 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3600 return false;
3601 }
3602
3603 GLenum sourceTarget = source->getTarget();
3604 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003605
3606 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003607 {
Geoff Lang4f0e0032017-05-01 16:04:35 -04003608 context->handleError(Error(GL_INVALID_VALUE, "Source texture level is not valid."));
Geoff Lang97073d12016-04-20 10:42:34 -07003609 return false;
3610 }
3611
Geoff Lang4f0e0032017-05-01 16:04:35 -04003612 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3613 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3614 if (sourceWidth == 0 || sourceHeight == 0)
3615 {
3616 context->handleError(
3617 Error(GL_INVALID_VALUE, "The source level of the source texture must be defined."));
3618 return false;
3619 }
3620
3621 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3622 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003623 {
3624 context->handleError(
3625 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3626 return false;
3627 }
3628
Geoff Lang4f0e0032017-05-01 16:04:35 -04003629 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003630 if (dest == nullptr)
3631 {
3632 context->handleError(
3633 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3634 return false;
3635 }
3636
Geoff Lang4f0e0032017-05-01 16:04:35 -04003637 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003638 {
3639 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3640 return false;
3641 }
3642
Geoff Lang4f0e0032017-05-01 16:04:35 -04003643 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3644 sourceHeight))
3645 {
3646 context->handleError(Error(GL_INVALID_VALUE, "Destination texture level is not valid."));
3647 return false;
3648 }
3649
Geoff Lang97073d12016-04-20 10:42:34 -07003650 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3651 {
3652 context->handleError(
3653 Error(GL_INVALID_OPERATION,
3654 "Destination internal format and type combination is not valid."));
3655 return false;
3656 }
3657
Geoff Lang4f0e0032017-05-01 16:04:35 -04003658 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3659 {
3660 context->handleError(Error(
3661 GL_INVALID_VALUE, "Destination width and height must be equal for cube map textures."));
3662 return false;
3663 }
3664
Geoff Lang97073d12016-04-20 10:42:34 -07003665 if (dest->getImmutableFormat())
3666 {
3667 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3668 return false;
3669 }
3670
3671 return true;
3672}
3673
3674bool ValidateCopySubTextureCHROMIUM(Context *context,
3675 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003676 GLint sourceLevel,
3677 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003678 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003679 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003680 GLint xoffset,
3681 GLint yoffset,
3682 GLint x,
3683 GLint y,
3684 GLsizei width,
3685 GLsizei height,
3686 GLboolean unpackFlipY,
3687 GLboolean unpackPremultiplyAlpha,
3688 GLboolean unpackUnmultiplyAlpha)
3689{
3690 if (!context->getExtensions().copyTexture)
3691 {
3692 context->handleError(
3693 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3694 return false;
3695 }
3696
Geoff Lang4f0e0032017-05-01 16:04:35 -04003697 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003698 if (source == nullptr)
3699 {
3700 context->handleError(
3701 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3702 return false;
3703 }
3704
3705 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3706 {
3707 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3708 return false;
3709 }
3710
3711 GLenum sourceTarget = source->getTarget();
3712 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003713
3714 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3715 {
3716 context->handleError(Error(GL_INVALID_VALUE, "Source texture level is not valid."));
3717 return false;
3718 }
3719
3720 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3721 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003722 {
3723 context->handleError(
Geoff Lang4f0e0032017-05-01 16:04:35 -04003724 Error(GL_INVALID_VALUE, "The source level of the source texture must be defined."));
Geoff Lang97073d12016-04-20 10:42:34 -07003725 return false;
3726 }
3727
3728 if (x < 0 || y < 0)
3729 {
3730 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3731 return false;
3732 }
3733
3734 if (width < 0 || height < 0)
3735 {
3736 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3737 return false;
3738 }
3739
Geoff Lang4f0e0032017-05-01 16:04:35 -04003740 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3741 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003742 {
3743 context->handleError(
3744 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3745 return false;
3746 }
3747
Geoff Lang4f0e0032017-05-01 16:04:35 -04003748 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3749 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003750 {
3751 context->handleError(
3752 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3753 return false;
3754 }
3755
Geoff Lang4f0e0032017-05-01 16:04:35 -04003756 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003757 if (dest == nullptr)
3758 {
3759 context->handleError(
3760 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3761 return false;
3762 }
3763
Geoff Lang4f0e0032017-05-01 16:04:35 -04003764 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003765 {
3766 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3767 return false;
3768 }
3769
Geoff Lang4f0e0032017-05-01 16:04:35 -04003770 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003771 {
Geoff Lang4f0e0032017-05-01 16:04:35 -04003772 context->handleError(Error(GL_INVALID_VALUE, "Destination texture level is not valid."));
Geoff Lang97073d12016-04-20 10:42:34 -07003773 return false;
3774 }
3775
Geoff Lang4f0e0032017-05-01 16:04:35 -04003776 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3777 {
3778 context->handleError(Error(
3779 GL_INVALID_VALUE, "The destination level of the destination texture must be defined."));
3780 return false;
3781 }
3782
3783 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3784 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003785 {
3786 context->handleError(
3787 Error(GL_INVALID_OPERATION,
3788 "Destination internal format and type combination is not valid."));
3789 return false;
3790 }
3791
3792 if (xoffset < 0 || yoffset < 0)
3793 {
3794 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3795 return false;
3796 }
3797
Geoff Lang4f0e0032017-05-01 16:04:35 -04003798 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3799 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003800 {
3801 context->handleError(
3802 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3803 return false;
3804 }
3805
3806 return true;
3807}
3808
Geoff Lang47110bf2016-04-20 11:13:22 -07003809bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3810{
3811 if (!context->getExtensions().copyCompressedTexture)
3812 {
3813 context->handleError(Error(GL_INVALID_OPERATION,
3814 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3815 return false;
3816 }
3817
3818 const gl::Texture *source = context->getTexture(sourceId);
3819 if (source == nullptr)
3820 {
3821 context->handleError(
3822 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3823 return false;
3824 }
3825
3826 if (source->getTarget() != GL_TEXTURE_2D)
3827 {
3828 context->handleError(
3829 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3830 return false;
3831 }
3832
3833 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3834 {
3835 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3836 return false;
3837 }
3838
3839 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3840 if (!sourceFormat.info->compressed)
3841 {
3842 context->handleError(
3843 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3844 return false;
3845 }
3846
3847 const gl::Texture *dest = context->getTexture(destId);
3848 if (dest == nullptr)
3849 {
3850 context->handleError(
3851 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3852 return false;
3853 }
3854
3855 if (dest->getTarget() != GL_TEXTURE_2D)
3856 {
3857 context->handleError(
3858 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3859 return false;
3860 }
3861
3862 if (dest->getImmutableFormat())
3863 {
3864 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3865 return false;
3866 }
3867
3868 return true;
3869}
3870
Martin Radev4c4c8e72016-08-04 12:25:34 +03003871bool ValidateCreateShader(Context *context, GLenum type)
3872{
3873 switch (type)
3874 {
3875 case GL_VERTEX_SHADER:
3876 case GL_FRAGMENT_SHADER:
3877 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003878
Martin Radev4c4c8e72016-08-04 12:25:34 +03003879 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003880 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003881 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003882 context->handleError(
3883 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3884 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003885 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003886 break;
3887
Martin Radev4c4c8e72016-08-04 12:25:34 +03003888 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003889 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003890 return false;
3891 }
Jamie Madill29639852016-09-02 15:00:09 -04003892
3893 return true;
3894}
3895
3896bool ValidateBufferData(ValidationContext *context,
3897 GLenum target,
3898 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003899 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003900 GLenum usage)
3901{
3902 if (size < 0)
3903 {
3904 context->handleError(Error(GL_INVALID_VALUE));
3905 return false;
3906 }
3907
3908 switch (usage)
3909 {
3910 case GL_STREAM_DRAW:
3911 case GL_STATIC_DRAW:
3912 case GL_DYNAMIC_DRAW:
3913 break;
3914
3915 case GL_STREAM_READ:
3916 case GL_STREAM_COPY:
3917 case GL_STATIC_READ:
3918 case GL_STATIC_COPY:
3919 case GL_DYNAMIC_READ:
3920 case GL_DYNAMIC_COPY:
3921 if (context->getClientMajorVersion() < 3)
3922 {
3923 context->handleError(Error(GL_INVALID_ENUM));
3924 return false;
3925 }
3926 break;
3927
3928 default:
3929 context->handleError(Error(GL_INVALID_ENUM));
3930 return false;
3931 }
3932
3933 if (!ValidBufferTarget(context, target))
3934 {
3935 context->handleError(Error(GL_INVALID_ENUM));
3936 return false;
3937 }
3938
3939 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3940
3941 if (!buffer)
3942 {
3943 context->handleError(Error(GL_INVALID_OPERATION));
3944 return false;
3945 }
3946
3947 return true;
3948}
3949
3950bool ValidateBufferSubData(ValidationContext *context,
3951 GLenum target,
3952 GLintptr offset,
3953 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003954 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003955{
3956 if (size < 0 || offset < 0)
3957 {
3958 context->handleError(Error(GL_INVALID_VALUE));
3959 return false;
3960 }
3961
3962 if (!ValidBufferTarget(context, target))
3963 {
3964 context->handleError(Error(GL_INVALID_ENUM));
3965 return false;
3966 }
3967
3968 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3969
3970 if (!buffer)
3971 {
3972 context->handleError(Error(GL_INVALID_OPERATION));
3973 return false;
3974 }
3975
3976 if (buffer->isMapped())
3977 {
3978 context->handleError(Error(GL_INVALID_OPERATION));
3979 return false;
3980 }
3981
3982 // Check for possible overflow of size + offset
3983 angle::CheckedNumeric<size_t> checkedSize(size);
3984 checkedSize += offset;
3985 if (!checkedSize.IsValid())
3986 {
3987 context->handleError(Error(GL_OUT_OF_MEMORY));
3988 return false;
3989 }
3990
3991 if (size + offset > buffer->getSize())
3992 {
3993 context->handleError(Error(GL_INVALID_VALUE));
3994 return false;
3995 }
3996
Martin Radev4c4c8e72016-08-04 12:25:34 +03003997 return true;
3998}
3999
Geoff Langc339c4e2016-11-29 10:37:36 -05004000bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004001{
Geoff Langc339c4e2016-11-29 10:37:36 -05004002 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004003 {
4004 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05004005 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04004006 return false;
4007 }
4008
4009 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
4010 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05004011 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04004012 {
Geoff Langc339c4e2016-11-29 10:37:36 -05004013 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04004014 return false;
4015 }
4016
4017 return true;
4018}
4019
Jamie Madillef300b12016-10-07 15:12:09 -04004020bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4021{
4022 if (texture < GL_TEXTURE0 ||
4023 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4024 {
4025 context->handleError(Error(GL_INVALID_ENUM));
4026 return false;
4027 }
4028
4029 return true;
4030}
4031
4032bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4033{
4034 Program *programObject = GetValidProgram(context, program);
4035 if (!programObject)
4036 {
4037 return false;
4038 }
4039
4040 Shader *shaderObject = GetValidShader(context, shader);
4041 if (!shaderObject)
4042 {
4043 return false;
4044 }
4045
4046 switch (shaderObject->getType())
4047 {
4048 case GL_VERTEX_SHADER:
4049 {
4050 if (programObject->getAttachedVertexShader())
4051 {
4052 context->handleError(Error(GL_INVALID_OPERATION));
4053 return false;
4054 }
4055 break;
4056 }
4057 case GL_FRAGMENT_SHADER:
4058 {
4059 if (programObject->getAttachedFragmentShader())
4060 {
4061 context->handleError(Error(GL_INVALID_OPERATION));
4062 return false;
4063 }
4064 break;
4065 }
4066 case GL_COMPUTE_SHADER:
4067 {
4068 if (programObject->getAttachedComputeShader())
4069 {
4070 context->handleError(Error(GL_INVALID_OPERATION));
4071 return false;
4072 }
4073 break;
4074 }
4075 default:
4076 UNREACHABLE();
4077 break;
4078 }
4079
4080 return true;
4081}
4082
Jamie Madill01a80ee2016-11-07 12:06:18 -05004083bool ValidateBindAttribLocation(ValidationContext *context,
4084 GLuint program,
4085 GLuint index,
4086 const GLchar *name)
4087{
4088 if (index >= MAX_VERTEX_ATTRIBS)
4089 {
4090 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
4091 return false;
4092 }
4093
4094 if (strncmp(name, "gl_", 3) == 0)
4095 {
4096 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
4097 return false;
4098 }
4099
Geoff Langfc32e8b2017-05-31 14:16:59 -04004100 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4101 // shader-related entry points
4102 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4103 {
4104 context->handleError(Error(GL_INVALID_VALUE, "Attribute name contains invalid characters"));
4105 return false;
4106 }
4107
Jamie Madill01a80ee2016-11-07 12:06:18 -05004108 return GetValidProgram(context, program) != nullptr;
4109}
4110
4111bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4112{
4113 if (!ValidBufferTarget(context, target))
4114 {
4115 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
4116 return false;
4117 }
4118
4119 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4120 !context->isBufferGenerated(buffer))
4121 {
4122 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
4123 return false;
4124 }
4125
4126 return true;
4127}
4128
4129bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4130{
4131 if (!ValidFramebufferTarget(target))
4132 {
4133 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4134 return false;
4135 }
4136
4137 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4138 !context->isFramebufferGenerated(framebuffer))
4139 {
4140 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
4141 return false;
4142 }
4143
4144 return true;
4145}
4146
4147bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4148{
4149 if (target != GL_RENDERBUFFER)
4150 {
4151 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
4152 return false;
4153 }
4154
4155 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4156 !context->isRenderbufferGenerated(renderbuffer))
4157 {
4158 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
4159 return false;
4160 }
4161
4162 return true;
4163}
4164
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004165static bool ValidBlendEquationMode(GLenum mode)
4166{
4167 switch (mode)
4168 {
4169 case GL_FUNC_ADD:
4170 case GL_FUNC_SUBTRACT:
4171 case GL_FUNC_REVERSE_SUBTRACT:
4172 case GL_MIN:
4173 case GL_MAX:
4174 return true;
4175
4176 default:
4177 return false;
4178 }
4179}
4180
Jamie Madillc1d770e2017-04-13 17:31:24 -04004181bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004182 GLfloat red,
4183 GLfloat green,
4184 GLfloat blue,
4185 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004186{
4187 return true;
4188}
4189
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004190bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4191{
4192 if (!ValidBlendEquationMode(mode))
4193 {
4194 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
4195 return false;
4196 }
4197
4198 return true;
4199}
4200
4201bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4202{
4203 if (!ValidBlendEquationMode(modeRGB))
4204 {
4205 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
4206 return false;
4207 }
4208
4209 if (!ValidBlendEquationMode(modeAlpha))
4210 {
4211 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
4212 return false;
4213 }
4214
4215 return true;
4216}
4217
4218bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4219{
4220 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4221}
4222
4223static bool ValidSrcBlendFunc(GLenum srcBlend)
4224{
4225 switch (srcBlend)
4226 {
4227 case GL_ZERO:
4228 case GL_ONE:
4229 case GL_SRC_COLOR:
4230 case GL_ONE_MINUS_SRC_COLOR:
4231 case GL_DST_COLOR:
4232 case GL_ONE_MINUS_DST_COLOR:
4233 case GL_SRC_ALPHA:
4234 case GL_ONE_MINUS_SRC_ALPHA:
4235 case GL_DST_ALPHA:
4236 case GL_ONE_MINUS_DST_ALPHA:
4237 case GL_CONSTANT_COLOR:
4238 case GL_ONE_MINUS_CONSTANT_COLOR:
4239 case GL_CONSTANT_ALPHA:
4240 case GL_ONE_MINUS_CONSTANT_ALPHA:
4241 case GL_SRC_ALPHA_SATURATE:
4242 return true;
4243
4244 default:
4245 return false;
4246 }
4247}
4248
4249static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4250{
4251 switch (dstBlend)
4252 {
4253 case GL_ZERO:
4254 case GL_ONE:
4255 case GL_SRC_COLOR:
4256 case GL_ONE_MINUS_SRC_COLOR:
4257 case GL_DST_COLOR:
4258 case GL_ONE_MINUS_DST_COLOR:
4259 case GL_SRC_ALPHA:
4260 case GL_ONE_MINUS_SRC_ALPHA:
4261 case GL_DST_ALPHA:
4262 case GL_ONE_MINUS_DST_ALPHA:
4263 case GL_CONSTANT_COLOR:
4264 case GL_ONE_MINUS_CONSTANT_COLOR:
4265 case GL_CONSTANT_ALPHA:
4266 case GL_ONE_MINUS_CONSTANT_ALPHA:
4267 return true;
4268
4269 case GL_SRC_ALPHA_SATURATE:
4270 return (contextMajorVersion >= 3);
4271
4272 default:
4273 return false;
4274 }
4275}
4276
4277bool ValidateBlendFuncSeparate(ValidationContext *context,
4278 GLenum srcRGB,
4279 GLenum dstRGB,
4280 GLenum srcAlpha,
4281 GLenum dstAlpha)
4282{
4283 if (!ValidSrcBlendFunc(srcRGB))
4284 {
4285 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4286 return false;
4287 }
4288
4289 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4290 {
4291 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4292 return false;
4293 }
4294
4295 if (!ValidSrcBlendFunc(srcAlpha))
4296 {
4297 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4298 return false;
4299 }
4300
4301 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4302 {
4303 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4304 return false;
4305 }
4306
Frank Henigman146e8a12017-03-02 23:22:37 -05004307 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4308 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004309 {
4310 bool constantColorUsed =
4311 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4312 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4313
4314 bool constantAlphaUsed =
4315 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4316 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4317
4318 if (constantColorUsed && constantAlphaUsed)
4319 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004320 const char *msg;
4321 if (context->getExtensions().webglCompatibility)
4322 {
4323 msg =
4324 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4325 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4326 }
4327 else
4328 {
4329 msg =
4330 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4331 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4332 "implementation.";
4333 ERR() << msg;
4334 }
4335 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004336 return false;
4337 }
4338 }
4339
4340 return true;
4341}
4342
Geoff Langc339c4e2016-11-29 10:37:36 -05004343bool ValidateGetString(Context *context, GLenum name)
4344{
4345 switch (name)
4346 {
4347 case GL_VENDOR:
4348 case GL_RENDERER:
4349 case GL_VERSION:
4350 case GL_SHADING_LANGUAGE_VERSION:
4351 case GL_EXTENSIONS:
4352 break;
4353
4354 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4355 if (!context->getExtensions().requestExtension)
4356 {
4357 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4358 return false;
4359 }
4360 break;
4361
4362 default:
4363 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4364 return false;
4365 }
4366
4367 return true;
4368}
4369
Geoff Lang47c48082016-12-07 15:38:13 -05004370bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4371{
4372 if (width <= 0.0f || isNaN(width))
4373 {
4374 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
4375 return false;
4376 }
4377
4378 return true;
4379}
4380
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004381bool ValidateVertexAttribPointer(ValidationContext *context,
4382 GLuint index,
4383 GLint size,
4384 GLenum type,
4385 GLboolean normalized,
4386 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004387 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004388{
Shao80957d92017-02-20 21:25:59 +08004389 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004390 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004391 return false;
4392 }
4393
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004394 if (stride < 0)
4395 {
Shao80957d92017-02-20 21:25:59 +08004396 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004397 return false;
4398 }
4399
Shao80957d92017-02-20 21:25:59 +08004400 const Caps &caps = context->getCaps();
4401 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004402 {
Shao80957d92017-02-20 21:25:59 +08004403 if (stride > caps.maxVertexAttribStride)
4404 {
4405 context->handleError(
4406 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
4407 return false;
4408 }
4409
4410 if (index >= caps.maxVertexAttribBindings)
4411 {
4412 context->handleError(
4413 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
4414 return false;
4415 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004416 }
4417
4418 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4419 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4420 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4421 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004422 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4423 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004424 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004425 {
4426 context->handleError(
4427 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08004428 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004429 return false;
4430 }
4431
4432 if (context->getExtensions().webglCompatibility)
4433 {
4434 // WebGL 1.0 [Section 6.14] Fixed point support
4435 // The WebGL API does not support the GL_FIXED data type.
4436 if (type == GL_FIXED)
4437 {
4438 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4439 return false;
4440 }
4441
Geoff Lang2d62ab72017-03-23 16:54:40 -04004442 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004443 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004444 return false;
4445 }
4446 }
4447
4448 return true;
4449}
4450
Jamie Madill876429b2017-04-20 15:46:24 -04004451bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004452{
4453 if (context->getExtensions().webglCompatibility && zNear > zFar)
4454 {
4455 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4456 return false;
4457 }
4458
4459 return true;
4460}
4461
Jamie Madille8fb6402017-02-14 17:56:40 -05004462bool ValidateRenderbufferStorage(ValidationContext *context,
4463 GLenum target,
4464 GLenum internalformat,
4465 GLsizei width,
4466 GLsizei height)
4467{
4468 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4469 height);
4470}
4471
4472bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4473 GLenum target,
4474 GLsizei samples,
4475 GLenum internalformat,
4476 GLsizei width,
4477 GLsizei height)
4478{
4479 if (!context->getExtensions().framebufferMultisample)
4480 {
4481 context->handleError(
4482 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4483 return false;
4484 }
4485
4486 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4487 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4488 // generated.
4489 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4490 {
4491 context->handleError(Error(GL_INVALID_VALUE));
4492 return false;
4493 }
4494
4495 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4496 // the specified storage. This is different than ES 3.0 in which a sample number higher
4497 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4498 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4499 if (context->getClientMajorVersion() >= 3)
4500 {
4501 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4502 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4503 {
4504 context->handleError(Error(GL_OUT_OF_MEMORY));
4505 return false;
4506 }
4507 }
4508
4509 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4510 width, height);
4511}
4512
Jamie Madillc1d770e2017-04-13 17:31:24 -04004513bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4514{
4515 if (!ValidFramebufferTarget(target))
4516 {
4517 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4518 return false;
4519 }
4520
4521 return true;
4522}
4523
4524bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004525 GLfloat red,
4526 GLfloat green,
4527 GLfloat blue,
4528 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004529{
4530 return true;
4531}
4532
Jamie Madill876429b2017-04-20 15:46:24 -04004533bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004534{
4535 return true;
4536}
4537
4538bool ValidateClearStencil(ValidationContext *context, GLint s)
4539{
4540 return true;
4541}
4542
4543bool ValidateColorMask(ValidationContext *context,
4544 GLboolean red,
4545 GLboolean green,
4546 GLboolean blue,
4547 GLboolean alpha)
4548{
4549 return true;
4550}
4551
4552bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4553{
4554 return true;
4555}
4556
4557bool ValidateCreateProgram(ValidationContext *context)
4558{
4559 return true;
4560}
4561
4562bool ValidateCullFace(ValidationContext *context, GLenum mode)
4563{
4564 switch (mode)
4565 {
4566 case GL_FRONT:
4567 case GL_BACK:
4568 case GL_FRONT_AND_BACK:
4569 break;
4570
4571 default:
4572 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
4573 return false;
4574 }
4575
4576 return true;
4577}
4578
4579bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4580{
4581 if (program == 0)
4582 {
4583 return false;
4584 }
4585
4586 if (!context->getProgram(program))
4587 {
4588 if (context->getShader(program))
4589 {
4590 context->handleError(
4591 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
4592 return false;
4593 }
4594 else
4595 {
4596 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
4597 return false;
4598 }
4599 }
4600
4601 return true;
4602}
4603
4604bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4605{
4606 if (shader == 0)
4607 {
4608 return false;
4609 }
4610
4611 if (!context->getShader(shader))
4612 {
4613 if (context->getProgram(shader))
4614 {
4615 context->handleError(
4616 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
4617 return false;
4618 }
4619 else
4620 {
4621 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4622 return false;
4623 }
4624 }
4625
4626 return true;
4627}
4628
4629bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4630{
4631 switch (func)
4632 {
4633 case GL_NEVER:
4634 case GL_ALWAYS:
4635 case GL_LESS:
4636 case GL_LEQUAL:
4637 case GL_EQUAL:
4638 case GL_GREATER:
4639 case GL_GEQUAL:
4640 case GL_NOTEQUAL:
4641 break;
4642
4643 default:
4644 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4645 return false;
4646 }
4647
4648 return true;
4649}
4650
4651bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4652{
4653 return true;
4654}
4655
4656bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4657{
4658 Program *programObject = GetValidProgram(context, program);
4659 if (!programObject)
4660 {
4661 return false;
4662 }
4663
4664 Shader *shaderObject = GetValidShader(context, shader);
4665 if (!shaderObject)
4666 {
4667 return false;
4668 }
4669
4670 const Shader *attachedShader = nullptr;
4671
4672 switch (shaderObject->getType())
4673 {
4674 case GL_VERTEX_SHADER:
4675 {
4676 attachedShader = programObject->getAttachedVertexShader();
4677 break;
4678 }
4679 case GL_FRAGMENT_SHADER:
4680 {
4681 attachedShader = programObject->getAttachedFragmentShader();
4682 break;
4683 }
4684 case GL_COMPUTE_SHADER:
4685 {
4686 attachedShader = programObject->getAttachedComputeShader();
4687 break;
4688 }
4689 default:
4690 UNREACHABLE();
4691 return false;
4692 }
4693
4694 if (attachedShader != shaderObject)
4695 {
4696 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4697 return false;
4698 }
4699
4700 return true;
4701}
4702
4703bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4704{
4705 if (index >= MAX_VERTEX_ATTRIBS)
4706 {
4707 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4708 return false;
4709 }
4710
4711 return true;
4712}
4713
4714bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4715{
4716 if (index >= MAX_VERTEX_ATTRIBS)
4717 {
4718 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4719 return false;
4720 }
4721
4722 return true;
4723}
4724
4725bool ValidateFinish(ValidationContext *context)
4726{
4727 return true;
4728}
4729
4730bool ValidateFlush(ValidationContext *context)
4731{
4732 return true;
4733}
4734
4735bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4736{
4737 switch (mode)
4738 {
4739 case GL_CW:
4740 case GL_CCW:
4741 break;
4742 default:
4743 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4744 return false;
4745 }
4746
4747 return true;
4748}
4749
4750bool ValidateGetActiveAttrib(ValidationContext *context,
4751 GLuint program,
4752 GLuint index,
4753 GLsizei bufsize,
4754 GLsizei *length,
4755 GLint *size,
4756 GLenum *type,
4757 GLchar *name)
4758{
4759 if (bufsize < 0)
4760 {
4761 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4762 return false;
4763 }
4764
4765 Program *programObject = GetValidProgram(context, program);
4766
4767 if (!programObject)
4768 {
4769 return false;
4770 }
4771
4772 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4773 {
4774 context->handleError(
4775 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4776 return false;
4777 }
4778
4779 return true;
4780}
4781
4782bool ValidateGetActiveUniform(ValidationContext *context,
4783 GLuint program,
4784 GLuint index,
4785 GLsizei bufsize,
4786 GLsizei *length,
4787 GLint *size,
4788 GLenum *type,
4789 GLchar *name)
4790{
4791 if (bufsize < 0)
4792 {
4793 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4794 return false;
4795 }
4796
4797 Program *programObject = GetValidProgram(context, program);
4798
4799 if (!programObject)
4800 {
4801 return false;
4802 }
4803
4804 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4805 {
4806 context->handleError(
4807 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4808 return false;
4809 }
4810
4811 return true;
4812}
4813
4814bool ValidateGetAttachedShaders(ValidationContext *context,
4815 GLuint program,
4816 GLsizei maxcount,
4817 GLsizei *count,
4818 GLuint *shaders)
4819{
4820 if (maxcount < 0)
4821 {
4822 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4823 return false;
4824 }
4825
4826 Program *programObject = GetValidProgram(context, program);
4827
4828 if (!programObject)
4829 {
4830 return false;
4831 }
4832
4833 return true;
4834}
4835
4836bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4837{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004838 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4839 // shader-related entry points
4840 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4841 {
4842 context->handleError(Error(GL_INVALID_VALUE, "Attribute name contains invalid characters"));
4843 return false;
4844 }
4845
Jamie Madillc1d770e2017-04-13 17:31:24 -04004846 Program *programObject = GetValidProgram(context, program);
4847
4848 if (!programObject)
4849 {
4850 return false;
4851 }
4852
4853 if (!programObject->isLinked())
4854 {
4855 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4856 return false;
4857 }
4858
4859 return true;
4860}
4861
4862bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4863{
4864 GLenum nativeType;
4865 unsigned int numParams = 0;
4866 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4867}
4868
4869bool ValidateGetError(ValidationContext *context)
4870{
4871 return true;
4872}
4873
4874bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4875{
4876 GLenum nativeType;
4877 unsigned int numParams = 0;
4878 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4879}
4880
4881bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4882{
4883 GLenum nativeType;
4884 unsigned int numParams = 0;
4885 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4886}
4887
4888bool ValidateGetProgramInfoLog(ValidationContext *context,
4889 GLuint program,
4890 GLsizei bufsize,
4891 GLsizei *length,
4892 GLchar *infolog)
4893{
4894 if (bufsize < 0)
4895 {
4896 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4897 return false;
4898 }
4899
4900 Program *programObject = GetValidProgram(context, program);
4901 if (!programObject)
4902 {
4903 return false;
4904 }
4905
4906 return true;
4907}
4908
4909bool ValidateGetShaderInfoLog(ValidationContext *context,
4910 GLuint shader,
4911 GLsizei bufsize,
4912 GLsizei *length,
4913 GLchar *infolog)
4914{
4915 if (bufsize < 0)
4916 {
4917 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4918 return false;
4919 }
4920
4921 Shader *shaderObject = GetValidShader(context, shader);
4922 if (!shaderObject)
4923 {
4924 return false;
4925 }
4926
4927 return true;
4928}
4929
4930bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4931 GLenum shadertype,
4932 GLenum precisiontype,
4933 GLint *range,
4934 GLint *precision)
4935{
4936 switch (shadertype)
4937 {
4938 case GL_VERTEX_SHADER:
4939 case GL_FRAGMENT_SHADER:
4940 break;
4941 case GL_COMPUTE_SHADER:
4942 context->handleError(
4943 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4944 return false;
4945 default:
4946 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4947 return false;
4948 }
4949
4950 switch (precisiontype)
4951 {
4952 case GL_LOW_FLOAT:
4953 case GL_MEDIUM_FLOAT:
4954 case GL_HIGH_FLOAT:
4955 case GL_LOW_INT:
4956 case GL_MEDIUM_INT:
4957 case GL_HIGH_INT:
4958 break;
4959
4960 default:
4961 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4962 return false;
4963 }
4964
4965 return true;
4966}
4967
4968bool ValidateGetShaderSource(ValidationContext *context,
4969 GLuint shader,
4970 GLsizei bufsize,
4971 GLsizei *length,
4972 GLchar *source)
4973{
4974 if (bufsize < 0)
4975 {
4976 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4977 return false;
4978 }
4979
4980 Shader *shaderObject = GetValidShader(context, shader);
4981 if (!shaderObject)
4982 {
4983 return false;
4984 }
4985
4986 return true;
4987}
4988
4989bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4990{
4991 if (strstr(name, "gl_") == name)
4992 {
4993 return false;
4994 }
4995
Geoff Langfc32e8b2017-05-31 14:16:59 -04004996 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4997 // shader-related entry points
4998 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4999 {
5000 context->handleError(Error(GL_INVALID_VALUE, "Uniform name contains invalid characters"));
5001 return false;
5002 }
5003
Jamie Madillc1d770e2017-04-13 17:31:24 -04005004 Program *programObject = GetValidProgram(context, program);
5005
5006 if (!programObject)
5007 {
5008 return false;
5009 }
5010
5011 if (!programObject->isLinked())
5012 {
5013 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
5014 return false;
5015 }
5016
5017 return true;
5018}
5019
5020bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5021{
5022 switch (mode)
5023 {
5024 case GL_FASTEST:
5025 case GL_NICEST:
5026 case GL_DONT_CARE:
5027 break;
5028
5029 default:
5030 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
5031 return false;
5032 }
5033
5034 switch (target)
5035 {
5036 case GL_GENERATE_MIPMAP_HINT:
5037 break;
5038
5039 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
5040 if (!context->getExtensions().standardDerivatives)
5041 {
5042 context->handleError(
5043 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
5044 return false;
5045 }
5046 break;
5047
5048 default:
5049 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
5050 return false;
5051 }
5052
5053 return true;
5054}
5055
5056bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5057{
5058 return true;
5059}
5060
5061bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5062{
5063 return true;
5064}
5065
5066bool ValidateIsProgram(ValidationContext *context, GLuint program)
5067{
5068 return true;
5069}
5070
5071bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5072{
5073 return true;
5074}
5075
5076bool ValidateIsShader(ValidationContext *context, GLuint shader)
5077{
5078 return true;
5079}
5080
5081bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5082{
5083 return true;
5084}
5085
5086bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5087{
5088 if (context->getClientMajorVersion() < 3)
5089 {
5090 switch (pname)
5091 {
5092 case GL_UNPACK_IMAGE_HEIGHT:
5093 case GL_UNPACK_SKIP_IMAGES:
5094 context->handleError(Error(GL_INVALID_ENUM));
5095 return false;
5096
5097 case GL_UNPACK_ROW_LENGTH:
5098 case GL_UNPACK_SKIP_ROWS:
5099 case GL_UNPACK_SKIP_PIXELS:
5100 if (!context->getExtensions().unpackSubimage)
5101 {
5102 context->handleError(Error(GL_INVALID_ENUM));
5103 return false;
5104 }
5105 break;
5106
5107 case GL_PACK_ROW_LENGTH:
5108 case GL_PACK_SKIP_ROWS:
5109 case GL_PACK_SKIP_PIXELS:
5110 if (!context->getExtensions().packSubimage)
5111 {
5112 context->handleError(Error(GL_INVALID_ENUM));
5113 return false;
5114 }
5115 break;
5116 }
5117 }
5118
5119 if (param < 0)
5120 {
5121 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
5122 return false;
5123 }
5124
5125 switch (pname)
5126 {
5127 case GL_UNPACK_ALIGNMENT:
5128 if (param != 1 && param != 2 && param != 4 && param != 8)
5129 {
5130 context->handleError(Error(GL_INVALID_VALUE));
5131 return false;
5132 }
5133 break;
5134
5135 case GL_PACK_ALIGNMENT:
5136 if (param != 1 && param != 2 && param != 4 && param != 8)
5137 {
5138 context->handleError(Error(GL_INVALID_VALUE));
5139 return false;
5140 }
5141 break;
5142
5143 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5144 case GL_UNPACK_ROW_LENGTH:
5145 case GL_UNPACK_IMAGE_HEIGHT:
5146 case GL_UNPACK_SKIP_IMAGES:
5147 case GL_UNPACK_SKIP_ROWS:
5148 case GL_UNPACK_SKIP_PIXELS:
5149 case GL_PACK_ROW_LENGTH:
5150 case GL_PACK_SKIP_ROWS:
5151 case GL_PACK_SKIP_PIXELS:
5152 break;
5153
5154 default:
5155 context->handleError(Error(GL_INVALID_ENUM));
5156 return false;
5157 }
5158
5159 return true;
5160}
5161
5162bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5163{
5164 return true;
5165}
5166
5167bool ValidateReleaseShaderCompiler(ValidationContext *context)
5168{
5169 return true;
5170}
5171
Jamie Madill876429b2017-04-20 15:46:24 -04005172bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005173{
5174 return true;
5175}
5176
5177bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5178{
5179 if (width < 0 || height < 0)
5180 {
5181 context->handleError(
5182 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
5183 return false;
5184 }
5185
5186 return true;
5187}
5188
5189bool ValidateShaderBinary(ValidationContext *context,
5190 GLsizei n,
5191 const GLuint *shaders,
5192 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005193 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005194 GLsizei length)
5195{
5196 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5197 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5198 shaderBinaryFormats.end())
5199 {
5200 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
5201 return false;
5202 }
5203
5204 return true;
5205}
5206
5207bool ValidateShaderSource(ValidationContext *context,
5208 GLuint shader,
5209 GLsizei count,
5210 const GLchar *const *string,
5211 const GLint *length)
5212{
5213 if (count < 0)
5214 {
5215 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
5216 return false;
5217 }
5218
Geoff Langfc32e8b2017-05-31 14:16:59 -04005219 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5220 // shader-related entry points
5221 if (context->getExtensions().webglCompatibility)
5222 {
5223 for (GLsizei i = 0; i < count; i++)
5224 {
5225 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
5226 if (!IsValidESSLString(string[i], len))
5227 {
5228 context->handleError(
5229 Error(GL_INVALID_VALUE, "Shader source contains invalid characters"));
5230 return false;
5231 }
5232 }
5233 }
5234
Jamie Madillc1d770e2017-04-13 17:31:24 -04005235 Shader *shaderObject = GetValidShader(context, shader);
5236 if (!shaderObject)
5237 {
5238 return false;
5239 }
5240
5241 return true;
5242}
5243
5244bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5245{
5246 if (!IsValidStencilFunc(func))
5247 {
5248 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
5249 return false;
5250 }
5251
5252 return true;
5253}
5254
5255bool ValidateStencilFuncSeparate(ValidationContext *context,
5256 GLenum face,
5257 GLenum func,
5258 GLint ref,
5259 GLuint mask)
5260{
5261 if (!IsValidStencilFace(face))
5262 {
5263 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5264 return false;
5265 }
5266
5267 if (!IsValidStencilFunc(func))
5268 {
5269 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
5270 return false;
5271 }
5272
5273 return true;
5274}
5275
5276bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5277{
5278 return true;
5279}
5280
5281bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5282{
5283 if (!IsValidStencilFace(face))
5284 {
5285 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5286 return false;
5287 }
5288
5289 return true;
5290}
5291
5292bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5293{
5294 if (!IsValidStencilOp(fail))
5295 {
5296 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
5297 return false;
5298 }
5299
5300 if (!IsValidStencilOp(zfail))
5301 {
5302 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
5303 return false;
5304 }
5305
5306 if (!IsValidStencilOp(zpass))
5307 {
5308 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
5309 return false;
5310 }
5311
5312 return true;
5313}
5314
5315bool ValidateStencilOpSeparate(ValidationContext *context,
5316 GLenum face,
5317 GLenum fail,
5318 GLenum zfail,
5319 GLenum zpass)
5320{
5321 if (!IsValidStencilFace(face))
5322 {
5323 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5324 return false;
5325 }
5326
5327 return ValidateStencilOp(context, fail, zfail, zpass);
5328}
5329
5330bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5331{
5332 return ValidateUniform(context, GL_FLOAT, location, 1);
5333}
5334
5335bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5336{
5337 return ValidateUniform(context, GL_FLOAT, location, count);
5338}
5339
Jamie Madillbe849e42017-05-02 15:49:00 -04005340bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5341{
5342 return ValidateUniform1iv(context, location, 1, &x);
5343}
5344
Jamie Madillc1d770e2017-04-13 17:31:24 -04005345bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5346{
5347 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5348}
5349
5350bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5351{
5352 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5353}
5354
5355bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5356{
5357 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5358}
5359
5360bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5361{
5362 return ValidateUniform(context, GL_INT_VEC2, location, count);
5363}
5364
5365bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5366{
5367 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5368}
5369
5370bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5371{
5372 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5373}
5374
5375bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5376{
5377 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5378}
5379
5380bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5381{
5382 return ValidateUniform(context, GL_INT_VEC3, location, count);
5383}
5384
5385bool ValidateUniform4f(ValidationContext *context,
5386 GLint location,
5387 GLfloat x,
5388 GLfloat y,
5389 GLfloat z,
5390 GLfloat w)
5391{
5392 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5393}
5394
5395bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5396{
5397 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5398}
5399
5400bool ValidateUniform4i(ValidationContext *context,
5401 GLint location,
5402 GLint x,
5403 GLint y,
5404 GLint z,
5405 GLint w)
5406{
5407 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5408}
5409
5410bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5411{
5412 return ValidateUniform(context, GL_INT_VEC4, location, count);
5413}
5414
5415bool ValidateUniformMatrix2fv(ValidationContext *context,
5416 GLint location,
5417 GLsizei count,
5418 GLboolean transpose,
5419 const GLfloat *value)
5420{
5421 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5422}
5423
5424bool ValidateUniformMatrix3fv(ValidationContext *context,
5425 GLint location,
5426 GLsizei count,
5427 GLboolean transpose,
5428 const GLfloat *value)
5429{
5430 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5431}
5432
5433bool ValidateUniformMatrix4fv(ValidationContext *context,
5434 GLint location,
5435 GLsizei count,
5436 GLboolean transpose,
5437 const GLfloat *value)
5438{
5439 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5440}
5441
5442bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5443{
5444 Program *programObject = GetValidProgram(context, program);
5445
5446 if (!programObject)
5447 {
5448 return false;
5449 }
5450
5451 return true;
5452}
5453
5454bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5455{
5456 if (index >= MAX_VERTEX_ATTRIBS)
5457 {
5458 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
5459 return false;
5460 }
5461
5462 return true;
5463}
5464
5465bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5466{
5467 return ValidateVertexAttribIndex(context, index);
5468}
5469
5470bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5471{
5472 return ValidateVertexAttribIndex(context, index);
5473}
5474
5475bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5476{
5477 return ValidateVertexAttribIndex(context, index);
5478}
5479
5480bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5481{
5482 return ValidateVertexAttribIndex(context, index);
5483}
5484
5485bool ValidateVertexAttrib3f(ValidationContext *context,
5486 GLuint index,
5487 GLfloat x,
5488 GLfloat y,
5489 GLfloat z)
5490{
5491 return ValidateVertexAttribIndex(context, index);
5492}
5493
5494bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5495{
5496 return ValidateVertexAttribIndex(context, index);
5497}
5498
5499bool ValidateVertexAttrib4f(ValidationContext *context,
5500 GLuint index,
5501 GLfloat x,
5502 GLfloat y,
5503 GLfloat z,
5504 GLfloat w)
5505{
5506 return ValidateVertexAttribIndex(context, index);
5507}
5508
5509bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5510{
5511 return ValidateVertexAttribIndex(context, index);
5512}
5513
5514bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5515{
5516 if (width < 0 || height < 0)
5517 {
5518 context->handleError(
5519 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
5520 return false;
5521 }
5522
5523 return true;
5524}
5525
5526bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5527{
5528 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5529}
5530
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005531bool ValidateDrawElements(ValidationContext *context,
5532 GLenum mode,
5533 GLsizei count,
5534 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005535 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005536{
5537 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5538}
5539
Jamie Madillbe849e42017-05-02 15:49:00 -04005540bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5541 GLenum target,
5542 GLenum attachment,
5543 GLenum pname,
5544 GLint *params)
5545{
5546 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5547 nullptr);
5548}
5549
5550bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5551{
5552 return ValidateGetProgramivBase(context, program, pname, nullptr);
5553}
5554
5555bool ValidateCopyTexImage2D(ValidationContext *context,
5556 GLenum target,
5557 GLint level,
5558 GLenum internalformat,
5559 GLint x,
5560 GLint y,
5561 GLsizei width,
5562 GLsizei height,
5563 GLint border)
5564{
5565 if (context->getClientMajorVersion() < 3)
5566 {
5567 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5568 0, x, y, width, height, border);
5569 }
5570
5571 ASSERT(context->getClientMajorVersion() == 3);
5572 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5573 0, x, y, width, height, border);
5574}
5575
5576bool ValidateCopyTexSubImage2D(Context *context,
5577 GLenum target,
5578 GLint level,
5579 GLint xoffset,
5580 GLint yoffset,
5581 GLint x,
5582 GLint y,
5583 GLsizei width,
5584 GLsizei height)
5585{
5586 if (context->getClientMajorVersion() < 3)
5587 {
5588 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5589 yoffset, x, y, width, height, 0);
5590 }
5591
5592 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5593 yoffset, 0, x, y, width, height, 0);
5594}
5595
5596bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5597{
5598 return ValidateGenOrDelete(context, n);
5599}
5600
5601bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5602{
5603 return ValidateGenOrDelete(context, n);
5604}
5605
5606bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5607{
5608 return ValidateGenOrDelete(context, n);
5609}
5610
5611bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5612{
5613 return ValidateGenOrDelete(context, n);
5614}
5615
5616bool ValidateDisable(Context *context, GLenum cap)
5617{
5618 if (!ValidCap(context, cap, false))
5619 {
5620 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5621 return false;
5622 }
5623
5624 return true;
5625}
5626
5627bool ValidateEnable(Context *context, GLenum cap)
5628{
5629 if (!ValidCap(context, cap, false))
5630 {
5631 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5632 return false;
5633 }
5634
5635 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5636 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5637 {
5638 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5639 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5640
5641 // We also output an error message to the debugger window if tracing is active, so that
5642 // developers can see the error message.
5643 ERR() << errorMessage;
5644 return false;
5645 }
5646
5647 return true;
5648}
5649
5650bool ValidateFramebufferRenderbuffer(Context *context,
5651 GLenum target,
5652 GLenum attachment,
5653 GLenum renderbuffertarget,
5654 GLuint renderbuffer)
5655{
5656 if (!ValidFramebufferTarget(target) ||
5657 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5658 {
5659 context->handleError(Error(GL_INVALID_ENUM));
5660 return false;
5661 }
5662
5663 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5664 renderbuffertarget, renderbuffer);
5665}
5666
5667bool ValidateFramebufferTexture2D(Context *context,
5668 GLenum target,
5669 GLenum attachment,
5670 GLenum textarget,
5671 GLuint texture,
5672 GLint level)
5673{
5674 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5675 // extension
5676 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5677 level != 0)
5678 {
5679 context->handleError(Error(GL_INVALID_VALUE));
5680 return false;
5681 }
5682
5683 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5684 {
5685 return false;
5686 }
5687
5688 if (texture != 0)
5689 {
5690 gl::Texture *tex = context->getTexture(texture);
5691 ASSERT(tex);
5692
5693 const gl::Caps &caps = context->getCaps();
5694
5695 switch (textarget)
5696 {
5697 case GL_TEXTURE_2D:
5698 {
5699 if (level > gl::log2(caps.max2DTextureSize))
5700 {
5701 context->handleError(Error(GL_INVALID_VALUE));
5702 return false;
5703 }
5704 if (tex->getTarget() != GL_TEXTURE_2D)
5705 {
5706 context->handleError(Error(GL_INVALID_OPERATION,
5707 "Textarget must match the texture target type."));
5708 return false;
5709 }
5710 }
5711 break;
5712
5713 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5714 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5715 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5716 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5717 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5718 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5719 {
5720 if (level > gl::log2(caps.maxCubeMapTextureSize))
5721 {
5722 context->handleError(Error(GL_INVALID_VALUE));
5723 return false;
5724 }
5725 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5726 {
5727 context->handleError(Error(GL_INVALID_OPERATION,
5728 "Textarget must match the texture target type."));
5729 return false;
5730 }
5731 }
5732 break;
5733
5734 case GL_TEXTURE_2D_MULTISAMPLE:
5735 {
5736 if (context->getClientVersion() < ES_3_1)
5737 {
5738 context->handleError(Error(GL_INVALID_OPERATION,
5739 "Texture target requires at least OpenGL ES 3.1."));
5740 return false;
5741 }
5742
5743 if (level != 0)
5744 {
5745 context->handleError(
5746 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
5747 return false;
5748 }
5749 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5750 {
5751 context->handleError(Error(GL_INVALID_OPERATION,
5752 "Textarget must match the texture target type."));
5753 return false;
5754 }
5755 }
5756 break;
5757
5758 default:
5759 context->handleError(Error(GL_INVALID_ENUM));
5760 return false;
5761 }
5762
5763 const Format &format = tex->getFormat(textarget, level);
5764 if (format.info->compressed)
5765 {
5766 context->handleError(Error(GL_INVALID_OPERATION));
5767 return false;
5768 }
5769 }
5770
5771 return true;
5772}
5773
5774bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5775{
5776 return ValidateGenOrDelete(context, n);
5777}
5778
5779bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5780{
5781 return ValidateGenOrDelete(context, n);
5782}
5783
5784bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5785{
5786 return ValidateGenOrDelete(context, n);
5787}
5788
5789bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5790{
5791 return ValidateGenOrDelete(context, n);
5792}
5793
5794bool ValidateGenerateMipmap(Context *context, GLenum target)
5795{
5796 if (!ValidTextureTarget(context, target))
5797 {
5798 context->handleError(Error(GL_INVALID_ENUM));
5799 return false;
5800 }
5801
5802 Texture *texture = context->getTargetTexture(target);
5803
5804 if (texture == nullptr)
5805 {
5806 context->handleError(Error(GL_INVALID_OPERATION));
5807 return false;
5808 }
5809
5810 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5811
5812 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5813 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5814 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5815 {
5816 context->handleError(Error(GL_INVALID_OPERATION));
5817 return false;
5818 }
5819
5820 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5821 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5822 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5823
5824 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5825 // unsized formats or that are color renderable and filterable. Since we do not track if
5826 // the texture was created with sized or unsized format (only sized formats are stored),
5827 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5828 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5829 // textures since they're the only texture format that can be created with unsized formats
5830 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5831 // was the last version to use add them.
5832 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5833 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5834 {
5835 context->handleError(Error(GL_INVALID_OPERATION));
5836 return false;
5837 }
5838
Geoff Lang65ac5b92017-05-01 13:16:30 -04005839 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5840 bool supportsSRGBMipmapGeneration =
5841 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5842 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 {
Geoff Lang65ac5b92017-05-01 13:16:30 -04005844 context->handleError(
5845 Error(GL_INVALID_OPERATION, "Mipmap generation of sRGB textures is not allowed."));
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 return false;
5847 }
5848
5849 // Non-power of 2 ES2 check
5850 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5851 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5852 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5853 {
5854 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
5855 context->handleError(Error(GL_INVALID_OPERATION));
5856 return false;
5857 }
5858
5859 // Cube completeness check
5860 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5861 {
5862 context->handleError(Error(GL_INVALID_OPERATION));
5863 return false;
5864 }
5865
5866 return true;
5867}
5868
5869bool ValidateGetBufferParameteriv(ValidationContext *context,
5870 GLenum target,
5871 GLenum pname,
5872 GLint *params)
5873{
5874 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5875}
5876
5877bool ValidateGetRenderbufferParameteriv(Context *context,
5878 GLenum target,
5879 GLenum pname,
5880 GLint *params)
5881{
5882 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5883}
5884
5885bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5886{
5887 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5888}
5889
5890bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5891{
5892 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5893}
5894
5895bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5896{
5897 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5898}
5899
5900bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5901{
5902 return ValidateGetUniformBase(context, program, location);
5903}
5904
5905bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5906{
5907 return ValidateGetUniformBase(context, program, location);
5908}
5909
5910bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5911{
5912 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5913}
5914
5915bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5916{
5917 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5918}
5919
5920bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5921{
5922 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5923}
5924
5925bool ValidateIsEnabled(Context *context, GLenum cap)
5926{
5927 if (!ValidCap(context, cap, true))
5928 {
5929 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5930 return false;
5931 }
5932
5933 return true;
5934}
5935
5936bool ValidateLinkProgram(Context *context, GLuint program)
5937{
5938 if (context->hasActiveTransformFeedback(program))
5939 {
5940 // ES 3.0.4 section 2.15 page 91
5941 context->handleError(Error(GL_INVALID_OPERATION,
5942 "Cannot link program while program is associated with an active "
5943 "transform feedback object."));
5944 return false;
5945 }
5946
5947 Program *programObject = GetValidProgram(context, program);
5948 if (!programObject)
5949 {
5950 return false;
5951 }
5952
5953 return true;
5954}
5955
5956bool ValidateReadPixels(ValidationContext *context,
5957 GLint x,
5958 GLint y,
5959 GLsizei width,
5960 GLsizei height,
5961 GLenum format,
5962 GLenum type,
5963 void *pixels)
5964{
5965 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5966 nullptr, pixels);
5967}
5968
5969bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5970{
5971 return ValidateTexParameterBase(context, target, pname, -1, &param);
5972}
5973
5974bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5975{
5976 return ValidateTexParameterBase(context, target, pname, -1, params);
5977}
5978
5979bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5980{
5981 return ValidateTexParameterBase(context, target, pname, -1, &param);
5982}
5983
5984bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5985{
5986 return ValidateTexParameterBase(context, target, pname, -1, params);
5987}
5988
5989bool ValidateUseProgram(Context *context, GLuint program)
5990{
5991 if (program != 0)
5992 {
5993 Program *programObject = context->getProgram(program);
5994 if (!programObject)
5995 {
5996 // ES 3.1.0 section 7.3 page 72
5997 if (context->getShader(program))
5998 {
5999 context->handleError(
6000 Error(GL_INVALID_OPERATION,
6001 "Attempted to use a single shader instead of a shader program."));
6002 return false;
6003 }
6004 else
6005 {
6006 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
6007 return false;
6008 }
6009 }
6010 if (!programObject->isLinked())
6011 {
6012 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
6013 return false;
6014 }
6015 }
6016 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6017 {
6018 // ES 3.0.4 section 2.15 page 91
6019 context->handleError(
6020 Error(GL_INVALID_OPERATION,
6021 "Cannot change active program while transform feedback is unpaused."));
6022 return false;
6023 }
6024
6025 return true;
6026}
6027
Jamie Madillc29968b2016-01-20 11:17:23 -05006028} // namespace gl