blob: 4a922f06d3632617a2f38d44b93b80e95212346a [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
Jamie Madillc29968b2016-01-20 11:17:23 -0500784} // anonymous namespace
785
Geoff Langff5b2d52016-09-07 11:32:23 -0400786bool ValidateES2TexImageParameters(Context *context,
787 GLenum target,
788 GLint level,
789 GLenum internalformat,
790 bool isCompressed,
791 bool isSubImage,
792 GLint xoffset,
793 GLint yoffset,
794 GLsizei width,
795 GLsizei height,
796 GLint border,
797 GLenum format,
798 GLenum type,
799 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400800 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801{
Jamie Madill6f38f822014-06-06 17:12:20 -0400802 if (!ValidTexture2DDestinationTarget(context, target))
803 {
Jamie Madill437fa652016-05-03 15:13:24 -0400804 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400805 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400806 }
807
Austin Kinross08528e12015-10-07 16:24:40 -0700808 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 {
Jamie Madill437fa652016-05-03 15:13:24 -0400810 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400811 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 }
813
He Yunchaoced53ae2016-11-29 15:00:51 +0800814 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 std::numeric_limits<GLsizei>::max() - yoffset < height)
816 {
Jamie Madill437fa652016-05-03 15:13:24 -0400817 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 }
820
Geoff Lang005df412013-10-16 14:12:50 -0400821 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822 {
Jamie Madill437fa652016-05-03 15:13:24 -0400823 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400824 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 }
826
Geoff Langaae65a42014-05-26 12:43:44 -0400827 const gl::Caps &caps = context->getCaps();
828
Geoff Langa9be0dc2014-12-17 12:34:40 -0500829 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500831 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
832 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833 {
Jamie Madill437fa652016-05-03 15:13:24 -0400834 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500837 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500838 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500839 {
840 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 {
Jamie Madill437fa652016-05-03 15:13:24 -0400842 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400845
Geoff Langa9be0dc2014-12-17 12:34:40 -0500846 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
847 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
848 {
Jamie Madill437fa652016-05-03 15:13:24 -0400849 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500850 return false;
851 }
852 }
853 else
854 {
Jamie Madill437fa652016-05-03 15:13:24 -0400855 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 }
858
He Yunchaoced53ae2016-11-29 15:00:51 +0800859 gl::Texture *texture =
860 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 if (!texture)
862 {
Jamie Madill437fa652016-05-03 15:13:24 -0400863 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400864 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400865 }
866
Geoff Langa9be0dc2014-12-17 12:34:40 -0500867 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400868 {
Geoff Langca271392017-04-05 12:30:00 -0400869 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
870 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500871 {
872 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
873 return false;
874 }
875
Geoff Langa9be0dc2014-12-17 12:34:40 -0500876 if (format != GL_NONE)
877 {
Geoff Langca271392017-04-05 12:30:00 -0400878 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
879 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500880 {
Jamie Madill437fa652016-05-03 15:13:24 -0400881 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500882 return false;
883 }
884 }
885
886 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
887 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
888 {
Jamie Madill437fa652016-05-03 15:13:24 -0400889 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500890 return false;
891 }
892 }
893 else
894 {
Geoff Lang69cce582015-09-17 13:20:36 -0400895 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500896 {
Jamie Madill437fa652016-05-03 15:13:24 -0400897 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500898 return false;
899 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400900 }
901
902 // Verify zero border
903 if (border != 0)
904 {
Jamie Madill437fa652016-05-03 15:13:24 -0400905 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400906 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 }
908
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 if (isCompressed)
910 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400911 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400912 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
913 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 switch (actualInternalFormat)
915 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800916 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
917 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
918 if (!context->getExtensions().textureCompressionDXT1)
919 {
920 context->handleError(Error(GL_INVALID_ENUM));
921 return false;
922 }
923 break;
924 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
925 if (!context->getExtensions().textureCompressionDXT1)
926 {
927 context->handleError(Error(GL_INVALID_ENUM));
928 return false;
929 }
930 break;
931 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
932 if (!context->getExtensions().textureCompressionDXT5)
933 {
934 context->handleError(Error(GL_INVALID_ENUM));
935 return false;
936 }
937 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800938 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
939 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
940 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
941 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
942 if (!context->getExtensions().textureCompressionS3TCsRGB)
943 {
944 context->handleError(Error(GL_INVALID_ENUM));
945 return false;
946 }
947 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 case GL_ETC1_RGB8_OES:
949 if (!context->getExtensions().compressedETC1RGB8Texture)
950 {
951 context->handleError(Error(GL_INVALID_ENUM));
952 return false;
953 }
954 break;
955 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800956 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
957 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
958 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
959 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800960 if (!context->getExtensions().lossyETCDecode)
961 {
962 context->handleError(Error(
963 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
964 return false;
965 }
966 break;
967 default:
968 context->handleError(
969 Error(GL_INVALID_ENUM,
970 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400971 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400972 }
Geoff Lang966c9402017-04-18 12:38:27 -0400973
974 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -0400975 {
Geoff Lang966c9402017-04-18 12:38:27 -0400976 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
977 height, texture->getWidth(target, level),
978 texture->getHeight(target, level)))
979 {
980 context->handleError(
981 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
982 return false;
983 }
984
985 if (format != actualInternalFormat)
986 {
987 context->handleError(Error(
988 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
989 return false;
990 }
991 }
992 else
993 {
994 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
995 {
996 context->handleError(
997 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
998 return false;
999 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 }
1001 }
1002 else
1003 {
1004 // validate <type> by itself (used as secondary key below)
1005 switch (type)
1006 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001007 case GL_UNSIGNED_BYTE:
1008 case GL_UNSIGNED_SHORT_5_6_5:
1009 case GL_UNSIGNED_SHORT_4_4_4_4:
1010 case GL_UNSIGNED_SHORT_5_5_5_1:
1011 case GL_UNSIGNED_SHORT:
1012 case GL_UNSIGNED_INT:
1013 case GL_UNSIGNED_INT_24_8_OES:
1014 case GL_HALF_FLOAT_OES:
1015 case GL_FLOAT:
1016 break;
1017 default:
1018 context->handleError(Error(GL_INVALID_ENUM));
1019 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 }
1021
1022 // validate <format> + <type> combinations
1023 // - invalid <format> -> sets INVALID_ENUM
1024 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1025 switch (format)
1026 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001027 case GL_ALPHA:
1028 case GL_LUMINANCE:
1029 case GL_LUMINANCE_ALPHA:
1030 switch (type)
1031 {
1032 case GL_UNSIGNED_BYTE:
1033 case GL_FLOAT:
1034 case GL_HALF_FLOAT_OES:
1035 break;
1036 default:
1037 context->handleError(Error(GL_INVALID_OPERATION));
1038 return false;
1039 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_RED:
1042 case GL_RG:
1043 if (!context->getExtensions().textureRG)
1044 {
1045 context->handleError(Error(GL_INVALID_ENUM));
1046 return false;
1047 }
1048 switch (type)
1049 {
1050 case GL_UNSIGNED_BYTE:
1051 case GL_FLOAT:
1052 case GL_HALF_FLOAT_OES:
1053 break;
1054 default:
1055 context->handleError(Error(GL_INVALID_OPERATION));
1056 return false;
1057 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001059 case GL_RGB:
1060 switch (type)
1061 {
1062 case GL_UNSIGNED_BYTE:
1063 case GL_UNSIGNED_SHORT_5_6_5:
1064 case GL_FLOAT:
1065 case GL_HALF_FLOAT_OES:
1066 break;
1067 default:
1068 context->handleError(Error(GL_INVALID_OPERATION));
1069 return false;
1070 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_RGBA:
1073 switch (type)
1074 {
1075 case GL_UNSIGNED_BYTE:
1076 case GL_UNSIGNED_SHORT_4_4_4_4:
1077 case GL_UNSIGNED_SHORT_5_5_5_1:
1078 case GL_FLOAT:
1079 case GL_HALF_FLOAT_OES:
1080 break;
1081 default:
1082 context->handleError(Error(GL_INVALID_OPERATION));
1083 return false;
1084 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001086 case GL_BGRA_EXT:
1087 switch (type)
1088 {
1089 case GL_UNSIGNED_BYTE:
1090 break;
1091 default:
1092 context->handleError(Error(GL_INVALID_OPERATION));
1093 return false;
1094 }
1095 break;
1096 case GL_SRGB_EXT:
1097 case GL_SRGB_ALPHA_EXT:
1098 if (!context->getExtensions().sRGB)
1099 {
1100 context->handleError(Error(GL_INVALID_ENUM));
1101 return false;
1102 }
1103 switch (type)
1104 {
1105 case GL_UNSIGNED_BYTE:
1106 break;
1107 default:
1108 context->handleError(Error(GL_INVALID_OPERATION));
1109 return false;
1110 }
1111 break;
1112 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1113 // handled below
1114 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1115 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1116 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1117 break;
1118 case GL_DEPTH_COMPONENT:
1119 switch (type)
1120 {
1121 case GL_UNSIGNED_SHORT:
1122 case GL_UNSIGNED_INT:
1123 break;
1124 default:
1125 context->handleError(Error(GL_INVALID_OPERATION));
1126 return false;
1127 }
1128 break;
1129 case GL_DEPTH_STENCIL_OES:
1130 switch (type)
1131 {
1132 case GL_UNSIGNED_INT_24_8_OES:
1133 break;
1134 default:
1135 context->handleError(Error(GL_INVALID_OPERATION));
1136 return false;
1137 }
1138 break;
1139 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001140 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001141 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142 }
1143
1144 switch (format)
1145 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1147 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1148 if (context->getExtensions().textureCompressionDXT1)
1149 {
1150 context->handleError(Error(GL_INVALID_OPERATION));
1151 return false;
1152 }
1153 else
1154 {
1155 context->handleError(Error(GL_INVALID_ENUM));
1156 return false;
1157 }
1158 break;
1159 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1160 if (context->getExtensions().textureCompressionDXT3)
1161 {
1162 context->handleError(Error(GL_INVALID_OPERATION));
1163 return false;
1164 }
1165 else
1166 {
1167 context->handleError(Error(GL_INVALID_ENUM));
1168 return false;
1169 }
1170 break;
1171 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1172 if (context->getExtensions().textureCompressionDXT5)
1173 {
1174 context->handleError(Error(GL_INVALID_OPERATION));
1175 return false;
1176 }
1177 else
1178 {
1179 context->handleError(Error(GL_INVALID_ENUM));
1180 return false;
1181 }
1182 break;
1183 case GL_ETC1_RGB8_OES:
1184 if (context->getExtensions().compressedETC1RGB8Texture)
1185 {
1186 context->handleError(Error(GL_INVALID_OPERATION));
1187 return false;
1188 }
1189 else
1190 {
1191 context->handleError(Error(GL_INVALID_ENUM));
1192 return false;
1193 }
1194 break;
1195 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001196 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1197 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1198 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1199 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001200 if (context->getExtensions().lossyETCDecode)
1201 {
1202 context->handleError(
1203 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -08001204 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +08001205 return false;
1206 }
1207 else
1208 {
1209 context->handleError(Error(
1210 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1211 return false;
1212 }
1213 break;
1214 case GL_DEPTH_COMPONENT:
1215 case GL_DEPTH_STENCIL_OES:
1216 if (!context->getExtensions().depthTextures)
1217 {
1218 context->handleError(Error(GL_INVALID_VALUE));
1219 return false;
1220 }
1221 if (target != GL_TEXTURE_2D)
1222 {
1223 context->handleError(Error(GL_INVALID_OPERATION));
1224 return false;
1225 }
1226 // OES_depth_texture supports loading depth data and multiple levels,
1227 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001228 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001229 {
1230 context->handleError(Error(GL_INVALID_OPERATION));
1231 return false;
1232 }
1233 break;
1234 default:
1235 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001236 }
1237
1238 if (type == GL_FLOAT)
1239 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001240 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001241 {
Jamie Madill437fa652016-05-03 15:13:24 -04001242 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001243 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244 }
1245 }
1246 else if (type == GL_HALF_FLOAT_OES)
1247 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001248 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 {
Jamie Madill437fa652016-05-03 15:13:24 -04001250 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001251 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001252 }
1253 }
1254 }
1255
Geoff Langff5b2d52016-09-07 11:32:23 -04001256 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
1257 imageSize))
1258 {
1259 return false;
1260 }
1261
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 return true;
1263}
1264
He Yunchaoced53ae2016-11-29 15:00:51 +08001265bool ValidateES2TexStorageParameters(Context *context,
1266 GLenum target,
1267 GLsizei levels,
1268 GLenum internalformat,
1269 GLsizei width,
1270 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271{
1272 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1273 {
Jamie Madill437fa652016-05-03 15:13:24 -04001274 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001275 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001276 }
1277
1278 if (width < 1 || height < 1 || levels < 1)
1279 {
Jamie Madill437fa652016-05-03 15:13:24 -04001280 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001281 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282 }
1283
1284 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1285 {
Jamie Madill437fa652016-05-03 15:13:24 -04001286 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001287 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288 }
1289
1290 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1291 {
Jamie Madill437fa652016-05-03 15:13:24 -04001292 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001293 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294 }
1295
Geoff Langca271392017-04-05 12:30:00 -04001296 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001297 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001298 {
Jamie Madill437fa652016-05-03 15:13:24 -04001299 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 }
1302
Geoff Langaae65a42014-05-26 12:43:44 -04001303 const gl::Caps &caps = context->getCaps();
1304
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305 switch (target)
1306 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001307 case GL_TEXTURE_2D:
1308 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1309 static_cast<GLuint>(height) > caps.max2DTextureSize)
1310 {
1311 context->handleError(Error(GL_INVALID_VALUE));
1312 return false;
1313 }
1314 break;
1315 case GL_TEXTURE_CUBE_MAP:
1316 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1317 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1318 {
1319 context->handleError(Error(GL_INVALID_VALUE));
1320 return false;
1321 }
1322 break;
1323 default:
1324 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326 }
1327
Geoff Langc0b9ef42014-07-02 10:02:37 -04001328 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 {
1330 if (!gl::isPow2(width) || !gl::isPow2(height))
1331 {
Jamie Madill437fa652016-05-03 15:13:24 -04001332 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
1335 }
1336
1337 switch (internalformat)
1338 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001339 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1340 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1341 if (!context->getExtensions().textureCompressionDXT1)
1342 {
1343 context->handleError(Error(GL_INVALID_ENUM));
1344 return false;
1345 }
1346 break;
1347 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1348 if (!context->getExtensions().textureCompressionDXT3)
1349 {
1350 context->handleError(Error(GL_INVALID_ENUM));
1351 return false;
1352 }
1353 break;
1354 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1355 if (!context->getExtensions().textureCompressionDXT5)
1356 {
1357 context->handleError(Error(GL_INVALID_ENUM));
1358 return false;
1359 }
1360 break;
1361 case GL_ETC1_RGB8_OES:
1362 if (!context->getExtensions().compressedETC1RGB8Texture)
1363 {
1364 context->handleError(Error(GL_INVALID_ENUM));
1365 return false;
1366 }
1367 break;
1368 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001369 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1370 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1371 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1372 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001373 if (!context->getExtensions().lossyETCDecode)
1374 {
1375 context->handleError(
1376 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1377 return false;
1378 }
1379 break;
1380 case GL_RGBA32F_EXT:
1381 case GL_RGB32F_EXT:
1382 case GL_ALPHA32F_EXT:
1383 case GL_LUMINANCE32F_EXT:
1384 case GL_LUMINANCE_ALPHA32F_EXT:
1385 if (!context->getExtensions().textureFloat)
1386 {
1387 context->handleError(Error(GL_INVALID_ENUM));
1388 return false;
1389 }
1390 break;
1391 case GL_RGBA16F_EXT:
1392 case GL_RGB16F_EXT:
1393 case GL_ALPHA16F_EXT:
1394 case GL_LUMINANCE16F_EXT:
1395 case GL_LUMINANCE_ALPHA16F_EXT:
1396 if (!context->getExtensions().textureHalfFloat)
1397 {
1398 context->handleError(Error(GL_INVALID_ENUM));
1399 return false;
1400 }
1401 break;
1402 case GL_R8_EXT:
1403 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001404 if (!context->getExtensions().textureRG)
1405 {
1406 context->handleError(Error(GL_INVALID_ENUM));
1407 return false;
1408 }
1409 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001410 case GL_R16F_EXT:
1411 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001412 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1413 {
1414 context->handleError(Error(GL_INVALID_ENUM));
1415 return false;
1416 }
1417 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001418 case GL_R32F_EXT:
1419 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001420 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001421 {
1422 context->handleError(Error(GL_INVALID_ENUM));
1423 return false;
1424 }
1425 break;
1426 case GL_DEPTH_COMPONENT16:
1427 case GL_DEPTH_COMPONENT32_OES:
1428 case GL_DEPTH24_STENCIL8_OES:
1429 if (!context->getExtensions().depthTextures)
1430 {
1431 context->handleError(Error(GL_INVALID_ENUM));
1432 return false;
1433 }
1434 if (target != GL_TEXTURE_2D)
1435 {
1436 context->handleError(Error(GL_INVALID_OPERATION));
1437 return false;
1438 }
1439 // ANGLE_depth_texture only supports 1-level textures
1440 if (levels != 1)
1441 {
1442 context->handleError(Error(GL_INVALID_OPERATION));
1443 return false;
1444 }
1445 break;
1446 default:
1447 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 }
1449
Geoff Lang691e58c2014-12-19 17:03:25 -05001450 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 if (!texture || texture->id() == 0)
1452 {
Jamie Madill437fa652016-05-03 15:13:24 -04001453 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001454 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001455 }
1456
Geoff Lang69cce582015-09-17 13:20:36 -04001457 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001458 {
Jamie Madill437fa652016-05-03 15:13:24 -04001459 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001460 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001461 }
1462
1463 return true;
1464}
1465
He Yunchaoced53ae2016-11-29 15:00:51 +08001466bool ValidateDiscardFramebufferEXT(Context *context,
1467 GLenum target,
1468 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001469 const GLenum *attachments)
1470{
Jamie Madillc29968b2016-01-20 11:17:23 -05001471 if (!context->getExtensions().discardFramebuffer)
1472 {
Jamie Madill437fa652016-05-03 15:13:24 -04001473 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001474 return false;
1475 }
1476
Austin Kinross08332632015-05-05 13:35:47 -07001477 bool defaultFramebuffer = false;
1478
1479 switch (target)
1480 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001481 case GL_FRAMEBUFFER:
1482 defaultFramebuffer =
1483 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1484 break;
1485 default:
1486 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1487 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001488 }
1489
He Yunchaoced53ae2016-11-29 15:00:51 +08001490 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1491 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001492}
1493
Austin Kinrossbc781f32015-10-26 09:27:38 -07001494bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1495{
1496 if (!context->getExtensions().vertexArrayObject)
1497 {
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001499 return false;
1500 }
1501
1502 return ValidateBindVertexArrayBase(context, array);
1503}
1504
1505bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1506{
1507 if (!context->getExtensions().vertexArrayObject)
1508 {
Jamie Madill437fa652016-05-03 15:13:24 -04001509 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001510 return false;
1511 }
1512
Olli Etuaho41997e72016-03-10 13:38:39 +02001513 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001514}
1515
1516bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1517{
1518 if (!context->getExtensions().vertexArrayObject)
1519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001521 return false;
1522 }
1523
Olli Etuaho41997e72016-03-10 13:38:39 +02001524 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001525}
1526
1527bool ValidateIsVertexArrayOES(Context *context)
1528{
1529 if (!context->getExtensions().vertexArrayObject)
1530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001532 return false;
1533 }
1534
1535 return true;
1536}
Geoff Langc5629752015-12-07 16:29:04 -05001537
1538bool ValidateProgramBinaryOES(Context *context,
1539 GLuint program,
1540 GLenum binaryFormat,
1541 const void *binary,
1542 GLint length)
1543{
1544 if (!context->getExtensions().getProgramBinary)
1545 {
Jamie Madill437fa652016-05-03 15:13:24 -04001546 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001547 return false;
1548 }
1549
1550 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1551}
1552
1553bool ValidateGetProgramBinaryOES(Context *context,
1554 GLuint program,
1555 GLsizei bufSize,
1556 GLsizei *length,
1557 GLenum *binaryFormat,
1558 void *binary)
1559{
1560 if (!context->getExtensions().getProgramBinary)
1561 {
Jamie Madill437fa652016-05-03 15:13:24 -04001562 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001563 return false;
1564 }
1565
1566 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1567}
Geoff Lange102fee2015-12-10 11:23:30 -05001568
Geoff Lang70d0f492015-12-10 17:45:46 -05001569static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1570{
1571 switch (source)
1572 {
1573 case GL_DEBUG_SOURCE_API:
1574 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1575 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1576 case GL_DEBUG_SOURCE_OTHER:
1577 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1578 return !mustBeThirdPartyOrApplication;
1579
1580 case GL_DEBUG_SOURCE_THIRD_PARTY:
1581 case GL_DEBUG_SOURCE_APPLICATION:
1582 return true;
1583
1584 default:
1585 return false;
1586 }
1587}
1588
1589static bool ValidDebugType(GLenum type)
1590{
1591 switch (type)
1592 {
1593 case GL_DEBUG_TYPE_ERROR:
1594 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1595 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1596 case GL_DEBUG_TYPE_PERFORMANCE:
1597 case GL_DEBUG_TYPE_PORTABILITY:
1598 case GL_DEBUG_TYPE_OTHER:
1599 case GL_DEBUG_TYPE_MARKER:
1600 case GL_DEBUG_TYPE_PUSH_GROUP:
1601 case GL_DEBUG_TYPE_POP_GROUP:
1602 return true;
1603
1604 default:
1605 return false;
1606 }
1607}
1608
1609static bool ValidDebugSeverity(GLenum severity)
1610{
1611 switch (severity)
1612 {
1613 case GL_DEBUG_SEVERITY_HIGH:
1614 case GL_DEBUG_SEVERITY_MEDIUM:
1615 case GL_DEBUG_SEVERITY_LOW:
1616 case GL_DEBUG_SEVERITY_NOTIFICATION:
1617 return true;
1618
1619 default:
1620 return false;
1621 }
1622}
1623
Geoff Lange102fee2015-12-10 11:23:30 -05001624bool ValidateDebugMessageControlKHR(Context *context,
1625 GLenum source,
1626 GLenum type,
1627 GLenum severity,
1628 GLsizei count,
1629 const GLuint *ids,
1630 GLboolean enabled)
1631{
1632 if (!context->getExtensions().debug)
1633 {
Jamie Madill437fa652016-05-03 15:13:24 -04001634 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001635 return false;
1636 }
1637
Geoff Lang70d0f492015-12-10 17:45:46 -05001638 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001641 return false;
1642 }
1643
1644 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1645 {
Jamie Madill437fa652016-05-03 15:13:24 -04001646 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001647 return false;
1648 }
1649
1650 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1651 {
Jamie Madill437fa652016-05-03 15:13:24 -04001652 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001653 return false;
1654 }
1655
1656 if (count > 0)
1657 {
1658 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1659 {
Jamie Madill437fa652016-05-03 15:13:24 -04001660 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001661 GL_INVALID_OPERATION,
1662 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1663 return false;
1664 }
1665
1666 if (severity != GL_DONT_CARE)
1667 {
Jamie Madill437fa652016-05-03 15:13:24 -04001668 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001669 Error(GL_INVALID_OPERATION,
1670 "If count is greater than zero, severity must be GL_DONT_CARE."));
1671 return false;
1672 }
1673 }
1674
Geoff Lange102fee2015-12-10 11:23:30 -05001675 return true;
1676}
1677
1678bool ValidateDebugMessageInsertKHR(Context *context,
1679 GLenum source,
1680 GLenum type,
1681 GLuint id,
1682 GLenum severity,
1683 GLsizei length,
1684 const GLchar *buf)
1685{
1686 if (!context->getExtensions().debug)
1687 {
Jamie Madill437fa652016-05-03 15:13:24 -04001688 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001689 return false;
1690 }
1691
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001692 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001693 {
1694 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1695 // not generate an error.
1696 return false;
1697 }
1698
1699 if (!ValidDebugSeverity(severity))
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001702 return false;
1703 }
1704
1705 if (!ValidDebugType(type))
1706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001708 return false;
1709 }
1710
1711 if (!ValidDebugSource(source, true))
1712 {
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001714 return false;
1715 }
1716
1717 size_t messageLength = (length < 0) ? strlen(buf) : length;
1718 if (messageLength > context->getExtensions().maxDebugMessageLength)
1719 {
Jamie Madill437fa652016-05-03 15:13:24 -04001720 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001721 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1722 return false;
1723 }
1724
Geoff Lange102fee2015-12-10 11:23:30 -05001725 return true;
1726}
1727
1728bool ValidateDebugMessageCallbackKHR(Context *context,
1729 GLDEBUGPROCKHR callback,
1730 const void *userParam)
1731{
1732 if (!context->getExtensions().debug)
1733 {
Jamie Madill437fa652016-05-03 15:13:24 -04001734 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001735 return false;
1736 }
1737
Geoff Lange102fee2015-12-10 11:23:30 -05001738 return true;
1739}
1740
1741bool ValidateGetDebugMessageLogKHR(Context *context,
1742 GLuint count,
1743 GLsizei bufSize,
1744 GLenum *sources,
1745 GLenum *types,
1746 GLuint *ids,
1747 GLenum *severities,
1748 GLsizei *lengths,
1749 GLchar *messageLog)
1750{
1751 if (!context->getExtensions().debug)
1752 {
Jamie Madill437fa652016-05-03 15:13:24 -04001753 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001754 return false;
1755 }
1756
Geoff Lang70d0f492015-12-10 17:45:46 -05001757 if (bufSize < 0 && messageLog != nullptr)
1758 {
Jamie Madill437fa652016-05-03 15:13:24 -04001759 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001760 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1761 return false;
1762 }
1763
Geoff Lange102fee2015-12-10 11:23:30 -05001764 return true;
1765}
1766
1767bool ValidatePushDebugGroupKHR(Context *context,
1768 GLenum source,
1769 GLuint id,
1770 GLsizei length,
1771 const GLchar *message)
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
Geoff Lang70d0f492015-12-10 17:45:46 -05001779 if (!ValidDebugSource(source, true))
1780 {
Jamie Madill437fa652016-05-03 15:13:24 -04001781 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001782 return false;
1783 }
1784
1785 size_t messageLength = (length < 0) ? strlen(message) : length;
1786 if (messageLength > context->getExtensions().maxDebugMessageLength)
1787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001789 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1790 return false;
1791 }
1792
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001793 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001794 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1795 {
Jamie Madill437fa652016-05-03 15:13:24 -04001796 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001797 Error(GL_STACK_OVERFLOW,
1798 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1799 return false;
1800 }
1801
Geoff Lange102fee2015-12-10 11:23:30 -05001802 return true;
1803}
1804
1805bool ValidatePopDebugGroupKHR(Context *context)
1806{
1807 if (!context->getExtensions().debug)
1808 {
Jamie Madill437fa652016-05-03 15:13:24 -04001809 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001810 return false;
1811 }
1812
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001813 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001814 if (currentStackSize <= 1)
1815 {
Jamie Madill437fa652016-05-03 15:13:24 -04001816 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001817 return false;
1818 }
1819
1820 return true;
1821}
1822
1823static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1824{
1825 switch (identifier)
1826 {
1827 case GL_BUFFER:
1828 if (context->getBuffer(name) == nullptr)
1829 {
Jamie Madill437fa652016-05-03 15:13:24 -04001830 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001831 return false;
1832 }
1833 return true;
1834
1835 case GL_SHADER:
1836 if (context->getShader(name) == nullptr)
1837 {
Jamie Madill437fa652016-05-03 15:13:24 -04001838 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001839 return false;
1840 }
1841 return true;
1842
1843 case GL_PROGRAM:
1844 if (context->getProgram(name) == nullptr)
1845 {
Jamie Madill437fa652016-05-03 15:13:24 -04001846 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001847 return false;
1848 }
1849 return true;
1850
1851 case GL_VERTEX_ARRAY:
1852 if (context->getVertexArray(name) == nullptr)
1853 {
Jamie Madill437fa652016-05-03 15:13:24 -04001854 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001855 return false;
1856 }
1857 return true;
1858
1859 case GL_QUERY:
1860 if (context->getQuery(name) == nullptr)
1861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001863 return false;
1864 }
1865 return true;
1866
1867 case GL_TRANSFORM_FEEDBACK:
1868 if (context->getTransformFeedback(name) == nullptr)
1869 {
Jamie Madill437fa652016-05-03 15:13:24 -04001870 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001871 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1872 return false;
1873 }
1874 return true;
1875
1876 case GL_SAMPLER:
1877 if (context->getSampler(name) == nullptr)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001880 return false;
1881 }
1882 return true;
1883
1884 case GL_TEXTURE:
1885 if (context->getTexture(name) == nullptr)
1886 {
Jamie Madill437fa652016-05-03 15:13:24 -04001887 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001888 return false;
1889 }
1890 return true;
1891
1892 case GL_RENDERBUFFER:
1893 if (context->getRenderbuffer(name) == nullptr)
1894 {
Jamie Madill437fa652016-05-03 15:13:24 -04001895 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001896 return false;
1897 }
1898 return true;
1899
1900 case GL_FRAMEBUFFER:
1901 if (context->getFramebuffer(name) == nullptr)
1902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 return false;
1905 }
1906 return true;
1907
1908 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001909 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001910 return false;
1911 }
Geoff Lange102fee2015-12-10 11:23:30 -05001912}
1913
Martin Radev9d901792016-07-15 15:58:58 +03001914static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1915{
1916 size_t labelLength = 0;
1917
1918 if (length < 0)
1919 {
1920 if (label != nullptr)
1921 {
1922 labelLength = strlen(label);
1923 }
1924 }
1925 else
1926 {
1927 labelLength = static_cast<size_t>(length);
1928 }
1929
1930 if (labelLength > context->getExtensions().maxLabelLength)
1931 {
1932 context->handleError(
1933 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1934 return false;
1935 }
1936
1937 return true;
1938}
1939
Geoff Lange102fee2015-12-10 11:23:30 -05001940bool ValidateObjectLabelKHR(Context *context,
1941 GLenum identifier,
1942 GLuint name,
1943 GLsizei length,
1944 const GLchar *label)
1945{
1946 if (!context->getExtensions().debug)
1947 {
Jamie Madill437fa652016-05-03 15:13:24 -04001948 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001949 return false;
1950 }
1951
Geoff Lang70d0f492015-12-10 17:45:46 -05001952 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1953 {
1954 return false;
1955 }
1956
Martin Radev9d901792016-07-15 15:58:58 +03001957 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001958 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001959 return false;
1960 }
1961
Geoff Lange102fee2015-12-10 11:23:30 -05001962 return true;
1963}
1964
1965bool ValidateGetObjectLabelKHR(Context *context,
1966 GLenum identifier,
1967 GLuint name,
1968 GLsizei bufSize,
1969 GLsizei *length,
1970 GLchar *label)
1971{
1972 if (!context->getExtensions().debug)
1973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001975 return false;
1976 }
1977
Geoff Lang70d0f492015-12-10 17:45:46 -05001978 if (bufSize < 0)
1979 {
Jamie Madill437fa652016-05-03 15:13:24 -04001980 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001981 return false;
1982 }
1983
1984 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1985 {
1986 return false;
1987 }
1988
Martin Radev9d901792016-07-15 15:58:58 +03001989 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001990}
1991
1992static bool ValidateObjectPtrName(Context *context, const void *ptr)
1993{
1994 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1995 {
Jamie Madill437fa652016-05-03 15:13:24 -04001996 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001997 return false;
1998 }
1999
Geoff Lange102fee2015-12-10 11:23:30 -05002000 return true;
2001}
2002
2003bool ValidateObjectPtrLabelKHR(Context *context,
2004 const void *ptr,
2005 GLsizei length,
2006 const GLchar *label)
2007{
2008 if (!context->getExtensions().debug)
2009 {
Jamie Madill437fa652016-05-03 15:13:24 -04002010 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002011 return false;
2012 }
2013
Geoff Lang70d0f492015-12-10 17:45:46 -05002014 if (!ValidateObjectPtrName(context, ptr))
2015 {
2016 return false;
2017 }
2018
Martin Radev9d901792016-07-15 15:58:58 +03002019 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002020 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002021 return false;
2022 }
2023
Geoff Lange102fee2015-12-10 11:23:30 -05002024 return true;
2025}
2026
2027bool ValidateGetObjectPtrLabelKHR(Context *context,
2028 const void *ptr,
2029 GLsizei bufSize,
2030 GLsizei *length,
2031 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 (bufSize < 0)
2040 {
Jamie Madill437fa652016-05-03 15:13:24 -04002041 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002042 return false;
2043 }
2044
2045 if (!ValidateObjectPtrName(context, ptr))
2046 {
2047 return false;
2048 }
2049
Martin Radev9d901792016-07-15 15:58:58 +03002050 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002051}
2052
2053bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2054{
2055 if (!context->getExtensions().debug)
2056 {
Jamie Madill437fa652016-05-03 15:13:24 -04002057 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05002058 return false;
2059 }
2060
Geoff Lang70d0f492015-12-10 17:45:46 -05002061 // TODO: represent this in Context::getQueryParameterInfo.
2062 switch (pname)
2063 {
2064 case GL_DEBUG_CALLBACK_FUNCTION:
2065 case GL_DEBUG_CALLBACK_USER_PARAM:
2066 break;
2067
2068 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002069 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05002070 return false;
2071 }
2072
Geoff Lange102fee2015-12-10 11:23:30 -05002073 return true;
2074}
Jamie Madillc29968b2016-01-20 11:17:23 -05002075
2076bool ValidateBlitFramebufferANGLE(Context *context,
2077 GLint srcX0,
2078 GLint srcY0,
2079 GLint srcX1,
2080 GLint srcY1,
2081 GLint dstX0,
2082 GLint dstY0,
2083 GLint dstX1,
2084 GLint dstY1,
2085 GLbitfield mask,
2086 GLenum filter)
2087{
2088 if (!context->getExtensions().framebufferBlit)
2089 {
Jamie Madill437fa652016-05-03 15:13:24 -04002090 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002091 return false;
2092 }
2093
2094 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2095 {
2096 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04002097 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05002098 GL_INVALID_OPERATION,
2099 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
2100 return false;
2101 }
2102
2103 if (filter == GL_LINEAR)
2104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002106 return false;
2107 }
2108
Jamie Madill51f40ec2016-06-15 14:06:00 -04002109 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2110 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002111
2112 if (mask & GL_COLOR_BUFFER_BIT)
2113 {
2114 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2115 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2116
2117 if (readColorAttachment && drawColorAttachment)
2118 {
2119 if (!(readColorAttachment->type() == GL_TEXTURE &&
2120 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2121 readColorAttachment->type() != GL_RENDERBUFFER &&
2122 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2123 {
Jamie Madill437fa652016-05-03 15:13:24 -04002124 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002125 return false;
2126 }
2127
Geoff Langa15472a2015-08-11 11:48:03 -04002128 for (size_t drawbufferIdx = 0;
2129 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002130 {
Geoff Langa15472a2015-08-11 11:48:03 -04002131 const FramebufferAttachment *attachment =
2132 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2133 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002134 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002135 if (!(attachment->type() == GL_TEXTURE &&
2136 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2137 attachment->type() != GL_RENDERBUFFER &&
2138 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2139 {
Jamie Madill437fa652016-05-03 15:13:24 -04002140 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002141 return false;
2142 }
2143
2144 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002145 if (!Format::SameSized(attachment->getFormat(),
2146 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002147 {
Jamie Madill437fa652016-05-03 15:13:24 -04002148 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002149 return false;
2150 }
2151 }
2152 }
2153
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002154 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002155 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2156 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2157 {
Jamie Madill437fa652016-05-03 15:13:24 -04002158 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002159 return false;
2160 }
2161 }
2162 }
2163
2164 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2165 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2166 for (size_t i = 0; i < 2; i++)
2167 {
2168 if (mask & masks[i])
2169 {
2170 const FramebufferAttachment *readBuffer =
2171 readFramebuffer->getAttachment(attachments[i]);
2172 const FramebufferAttachment *drawBuffer =
2173 drawFramebuffer->getAttachment(attachments[i]);
2174
2175 if (readBuffer && drawBuffer)
2176 {
2177 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2178 dstX0, dstY0, dstX1, dstY1))
2179 {
2180 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05002181 context->handleError(Error(GL_INVALID_OPERATION,
2182 "Only whole-buffer depth and stencil blits are "
2183 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002184 return false;
2185 }
2186
2187 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002190 return false;
2191 }
2192 }
2193 }
2194 }
2195
2196 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2197 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002198}
Jamie Madillc29968b2016-01-20 11:17:23 -05002199
2200bool ValidateClear(ValidationContext *context, GLbitfield mask)
2201{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002202 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002203 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002204 {
Jamie Madill437fa652016-05-03 15:13:24 -04002205 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002206 return false;
2207 }
2208
2209 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05002212 return false;
2213 }
2214
Geoff Lang76e65652017-03-27 14:58:02 -04002215 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2216 {
2217 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2218 GL_SIGNED_NORMALIZED};
2219
2220 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2221 drawBufferIdx++)
2222 {
2223 if (!ValidateWebGLFramebufferAttachmentClearType(
2224 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2225 {
2226 return false;
2227 }
2228 }
2229 }
2230
Jamie Madillc29968b2016-01-20 11:17:23 -05002231 return true;
2232}
2233
2234bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2235{
2236 if (!context->getExtensions().drawBuffers)
2237 {
Jamie Madill437fa652016-05-03 15:13:24 -04002238 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002239 return false;
2240 }
2241
2242 return ValidateDrawBuffersBase(context, n, bufs);
2243}
2244
Jamie Madill73a84962016-02-12 09:27:23 -05002245bool ValidateTexImage2D(Context *context,
2246 GLenum target,
2247 GLint level,
2248 GLint internalformat,
2249 GLsizei width,
2250 GLsizei height,
2251 GLint border,
2252 GLenum format,
2253 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002254 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002255{
Martin Radev1be913c2016-07-11 17:59:16 +03002256 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002257 {
2258 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002259 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002260 }
2261
Martin Radev1be913c2016-07-11 17:59:16 +03002262 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002263 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002264 0, 0, width, height, 1, border, format, type, -1,
2265 pixels);
2266}
2267
2268bool ValidateTexImage2DRobust(Context *context,
2269 GLenum target,
2270 GLint level,
2271 GLint internalformat,
2272 GLsizei width,
2273 GLsizei height,
2274 GLint border,
2275 GLenum format,
2276 GLenum type,
2277 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002278 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002279{
2280 if (!ValidateRobustEntryPoint(context, bufSize))
2281 {
2282 return false;
2283 }
2284
2285 if (context->getClientMajorVersion() < 3)
2286 {
2287 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2288 0, 0, width, height, border, format, type, bufSize,
2289 pixels);
2290 }
2291
2292 ASSERT(context->getClientMajorVersion() >= 3);
2293 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2294 0, 0, width, height, 1, border, format, type, bufSize,
2295 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002296}
2297
2298bool ValidateTexSubImage2D(Context *context,
2299 GLenum target,
2300 GLint level,
2301 GLint xoffset,
2302 GLint yoffset,
2303 GLsizei width,
2304 GLsizei height,
2305 GLenum format,
2306 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002307 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002308{
2309
Martin Radev1be913c2016-07-11 17:59:16 +03002310 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002311 {
2312 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002313 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002314 }
2315
Martin Radev1be913c2016-07-11 17:59:16 +03002316 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002317 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002318 yoffset, 0, width, height, 1, 0, format, type, -1,
2319 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002320}
2321
Geoff Langc52f6f12016-10-14 10:18:00 -04002322bool ValidateTexSubImage2DRobustANGLE(Context *context,
2323 GLenum target,
2324 GLint level,
2325 GLint xoffset,
2326 GLint yoffset,
2327 GLsizei width,
2328 GLsizei height,
2329 GLenum format,
2330 GLenum type,
2331 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002332 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002333{
2334 if (!ValidateRobustEntryPoint(context, bufSize))
2335 {
2336 return false;
2337 }
2338
2339 if (context->getClientMajorVersion() < 3)
2340 {
2341 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2342 yoffset, width, height, 0, format, type, bufSize,
2343 pixels);
2344 }
2345
2346 ASSERT(context->getClientMajorVersion() >= 3);
2347 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2348 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2349 pixels);
2350}
2351
Jamie Madill73a84962016-02-12 09:27:23 -05002352bool ValidateCompressedTexImage2D(Context *context,
2353 GLenum target,
2354 GLint level,
2355 GLenum internalformat,
2356 GLsizei width,
2357 GLsizei height,
2358 GLint border,
2359 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002360 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002361{
Martin Radev1be913c2016-07-11 17:59:16 +03002362 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002363 {
2364 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002365 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002366 {
2367 return false;
2368 }
2369 }
2370 else
2371 {
Martin Radev1be913c2016-07-11 17:59:16 +03002372 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002373 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002374 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002375 data))
2376 {
2377 return false;
2378 }
2379 }
2380
Geoff Langca271392017-04-05 12:30:00 -04002381 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002382 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002383 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002384 if (blockSizeOrErr.isError())
2385 {
2386 context->handleError(blockSizeOrErr.getError());
2387 return false;
2388 }
2389
2390 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002391 {
Jamie Madill437fa652016-05-03 15:13:24 -04002392 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002393 return false;
2394 }
2395
2396 return true;
2397}
2398
Corentin Wallezb2931602017-04-11 15:58:57 -04002399bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2400 GLenum target,
2401 GLint level,
2402 GLenum internalformat,
2403 GLsizei width,
2404 GLsizei height,
2405 GLint border,
2406 GLsizei imageSize,
2407 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002408 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002409{
2410 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2411 {
2412 return false;
2413 }
2414
2415 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2416 border, imageSize, data);
2417}
2418bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2419 GLenum target,
2420 GLint level,
2421 GLint xoffset,
2422 GLint yoffset,
2423 GLsizei width,
2424 GLsizei height,
2425 GLenum format,
2426 GLsizei imageSize,
2427 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002428 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002429{
2430 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2431 {
2432 return false;
2433 }
2434
2435 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2436 format, imageSize, data);
2437}
2438
Jamie Madill73a84962016-02-12 09:27:23 -05002439bool ValidateCompressedTexSubImage2D(Context *context,
2440 GLenum target,
2441 GLint level,
2442 GLint xoffset,
2443 GLint yoffset,
2444 GLsizei width,
2445 GLsizei height,
2446 GLenum format,
2447 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002448 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002449{
Martin Radev1be913c2016-07-11 17:59:16 +03002450 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002451 {
2452 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002453 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002454 {
2455 return false;
2456 }
2457 }
2458 else
2459 {
Martin Radev1be913c2016-07-11 17:59:16 +03002460 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002461 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002462 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002463 data))
2464 {
2465 return false;
2466 }
2467 }
2468
Geoff Langca271392017-04-05 12:30:00 -04002469 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002470 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002471 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002472 if (blockSizeOrErr.isError())
2473 {
2474 context->handleError(blockSizeOrErr.getError());
2475 return false;
2476 }
2477
2478 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002479 {
Jamie Madill437fa652016-05-03 15:13:24 -04002480 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002481 return false;
2482 }
2483
2484 return true;
2485}
2486
Olli Etuaho4f667482016-03-30 15:56:35 +03002487bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2488{
Geoff Lang496c02d2016-10-20 11:38:11 -07002489 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002490}
2491
2492bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2493{
2494 if (!context->getExtensions().mapBuffer)
2495 {
Jamie Madill437fa652016-05-03 15:13:24 -04002496 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002497 return false;
2498 }
2499
2500 if (!ValidBufferTarget(context, target))
2501 {
Jamie Madill437fa652016-05-03 15:13:24 -04002502 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002503 return false;
2504 }
2505
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002506 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002507
2508 if (buffer == nullptr)
2509 {
Jamie Madill437fa652016-05-03 15:13:24 -04002510 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002511 return false;
2512 }
2513
2514 if (access != GL_WRITE_ONLY_OES)
2515 {
Jamie Madill437fa652016-05-03 15:13:24 -04002516 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002517 return false;
2518 }
2519
2520 if (buffer->isMapped())
2521 {
Jamie Madill437fa652016-05-03 15:13:24 -04002522 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002523 return false;
2524 }
2525
2526 return true;
2527}
2528
2529bool ValidateUnmapBufferOES(Context *context, GLenum target)
2530{
2531 if (!context->getExtensions().mapBuffer)
2532 {
Jamie Madill437fa652016-05-03 15:13:24 -04002533 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002534 return false;
2535 }
2536
2537 return ValidateUnmapBufferBase(context, target);
2538}
2539
2540bool ValidateMapBufferRangeEXT(Context *context,
2541 GLenum target,
2542 GLintptr offset,
2543 GLsizeiptr length,
2544 GLbitfield access)
2545{
2546 if (!context->getExtensions().mapBufferRange)
2547 {
Jamie Madill437fa652016-05-03 15:13:24 -04002548 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002549 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2550 return false;
2551 }
2552
2553 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2554}
2555
2556bool ValidateFlushMappedBufferRangeEXT(Context *context,
2557 GLenum target,
2558 GLintptr offset,
2559 GLsizeiptr length)
2560{
2561 if (!context->getExtensions().mapBufferRange)
2562 {
Jamie Madill437fa652016-05-03 15:13:24 -04002563 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002564 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2565 return false;
2566 }
2567
2568 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2569}
2570
Ian Ewell54f87462016-03-10 13:47:21 -05002571bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2572{
2573 Texture *textureObject = context->getTexture(texture);
2574 if (textureObject && textureObject->getTarget() != target && texture != 0)
2575 {
Jamie Madill437fa652016-05-03 15:13:24 -04002576 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002577 return false;
2578 }
2579
Geoff Langf41a7152016-09-19 15:11:17 -04002580 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2581 !context->isTextureGenerated(texture))
2582 {
2583 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2584 return false;
2585 }
2586
Ian Ewell54f87462016-03-10 13:47:21 -05002587 switch (target)
2588 {
2589 case GL_TEXTURE_2D:
2590 case GL_TEXTURE_CUBE_MAP:
2591 break;
2592
2593 case GL_TEXTURE_3D:
2594 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002595 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002596 {
Jamie Madill437fa652016-05-03 15:13:24 -04002597 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002598 return false;
2599 }
2600 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002601
2602 case GL_TEXTURE_2D_MULTISAMPLE:
2603 if (context->getClientVersion() < Version(3, 1))
2604 {
2605 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2606 return false;
2607 }
Geoff Lang3b573612016-10-31 14:08:10 -04002608 break;
2609
Ian Ewell54f87462016-03-10 13:47:21 -05002610 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002611 if (!context->getExtensions().eglImageExternal &&
2612 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002613 {
Jamie Madill437fa652016-05-03 15:13:24 -04002614 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002615 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2616 return false;
2617 }
2618 break;
2619 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002620 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002621 return false;
2622 }
2623
2624 return true;
2625}
2626
Geoff Langd8605522016-04-13 10:19:12 -04002627bool ValidateBindUniformLocationCHROMIUM(Context *context,
2628 GLuint program,
2629 GLint location,
2630 const GLchar *name)
2631{
2632 if (!context->getExtensions().bindUniformLocation)
2633 {
Jamie Madill437fa652016-05-03 15:13:24 -04002634 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002635 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2636 return false;
2637 }
2638
2639 Program *programObject = GetValidProgram(context, program);
2640 if (!programObject)
2641 {
2642 return false;
2643 }
2644
2645 if (location < 0)
2646 {
Jamie Madill437fa652016-05-03 15:13:24 -04002647 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002648 return false;
2649 }
2650
2651 const Caps &caps = context->getCaps();
2652 if (static_cast<size_t>(location) >=
2653 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2654 {
Jamie Madill437fa652016-05-03 15:13:24 -04002655 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002656 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2657 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2658 return false;
2659 }
2660
2661 if (strncmp(name, "gl_", 3) == 0)
2662 {
Jamie Madill437fa652016-05-03 15:13:24 -04002663 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002664 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2665 return false;
2666 }
2667
2668 return true;
2669}
2670
Jamie Madille2e406c2016-06-02 13:04:10 -04002671bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002672{
2673 if (!context->getExtensions().framebufferMixedSamples)
2674 {
2675 context->handleError(
2676 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2677 return false;
2678 }
2679 switch (components)
2680 {
2681 case GL_RGB:
2682 case GL_RGBA:
2683 case GL_ALPHA:
2684 case GL_NONE:
2685 break;
2686 default:
2687 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002688 Error(GL_INVALID_ENUM,
2689 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002690 return false;
2691 }
2692
2693 return true;
2694}
2695
Sami Väisänene45e53b2016-05-25 10:36:04 +03002696// CHROMIUM_path_rendering
2697
2698bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2699{
2700 if (!context->getExtensions().pathRendering)
2701 {
2702 context->handleError(
2703 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2704 return false;
2705 }
2706 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2707 {
2708 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2709 return false;
2710 }
2711 if (matrix == nullptr)
2712 {
2713 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2714 return false;
2715 }
2716 return true;
2717}
2718
2719bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2720{
2721 if (!context->getExtensions().pathRendering)
2722 {
2723 context->handleError(
2724 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2725 return false;
2726 }
2727 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2728 {
2729 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2730 return false;
2731 }
2732 return true;
2733}
2734
2735bool ValidateGenPaths(Context *context, GLsizei range)
2736{
2737 if (!context->getExtensions().pathRendering)
2738 {
2739 context->handleError(
2740 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2741 return false;
2742 }
2743
2744 // range = 0 is undefined in NV_path_rendering.
2745 // we add stricter semantic check here and require a non zero positive range.
2746 if (range <= 0)
2747 {
2748 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2749 return false;
2750 }
2751
2752 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2753 {
2754 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2755 return false;
2756 }
2757
2758 return true;
2759}
2760
2761bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2762{
2763 if (!context->getExtensions().pathRendering)
2764 {
2765 context->handleError(
2766 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2767 return false;
2768 }
2769
2770 // range = 0 is undefined in NV_path_rendering.
2771 // we add stricter semantic check here and require a non zero positive range.
2772 if (range <= 0)
2773 {
2774 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2775 return false;
2776 }
2777
2778 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2779 checkedRange += range;
2780
2781 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2782 {
2783 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2784 return false;
2785 }
2786 return true;
2787}
2788
2789bool ValidatePathCommands(Context *context,
2790 GLuint path,
2791 GLsizei numCommands,
2792 const GLubyte *commands,
2793 GLsizei numCoords,
2794 GLenum coordType,
2795 const void *coords)
2796{
2797 if (!context->getExtensions().pathRendering)
2798 {
2799 context->handleError(
2800 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2801 return false;
2802 }
2803 if (!context->hasPath(path))
2804 {
2805 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2806 return false;
2807 }
2808
2809 if (numCommands < 0)
2810 {
2811 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2812 return false;
2813 }
2814 else if (numCommands > 0)
2815 {
2816 if (!commands)
2817 {
2818 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2819 return false;
2820 }
2821 }
2822
2823 if (numCoords < 0)
2824 {
2825 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2826 return false;
2827 }
2828 else if (numCoords > 0)
2829 {
2830 if (!coords)
2831 {
2832 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2833 return false;
2834 }
2835 }
2836
2837 std::uint32_t coordTypeSize = 0;
2838 switch (coordType)
2839 {
2840 case GL_BYTE:
2841 coordTypeSize = sizeof(GLbyte);
2842 break;
2843
2844 case GL_UNSIGNED_BYTE:
2845 coordTypeSize = sizeof(GLubyte);
2846 break;
2847
2848 case GL_SHORT:
2849 coordTypeSize = sizeof(GLshort);
2850 break;
2851
2852 case GL_UNSIGNED_SHORT:
2853 coordTypeSize = sizeof(GLushort);
2854 break;
2855
2856 case GL_FLOAT:
2857 coordTypeSize = sizeof(GLfloat);
2858 break;
2859
2860 default:
2861 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2862 return false;
2863 }
2864
2865 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2866 checkedSize += (coordTypeSize * numCoords);
2867 if (!checkedSize.IsValid())
2868 {
2869 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2870 return false;
2871 }
2872
2873 // early return skips command data validation when it doesn't exist.
2874 if (!commands)
2875 return true;
2876
2877 GLsizei expectedNumCoords = 0;
2878 for (GLsizei i = 0; i < numCommands; ++i)
2879 {
2880 switch (commands[i])
2881 {
2882 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2883 break;
2884 case GL_MOVE_TO_CHROMIUM:
2885 case GL_LINE_TO_CHROMIUM:
2886 expectedNumCoords += 2;
2887 break;
2888 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2889 expectedNumCoords += 4;
2890 break;
2891 case GL_CUBIC_CURVE_TO_CHROMIUM:
2892 expectedNumCoords += 6;
2893 break;
2894 case GL_CONIC_CURVE_TO_CHROMIUM:
2895 expectedNumCoords += 5;
2896 break;
2897 default:
2898 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2899 return false;
2900 }
2901 }
2902 if (expectedNumCoords != numCoords)
2903 {
2904 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2905 return false;
2906 }
2907
2908 return true;
2909}
2910
2911bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2912{
2913 if (!context->getExtensions().pathRendering)
2914 {
2915 context->handleError(
2916 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2917 return false;
2918 }
2919 if (!context->hasPath(path))
2920 {
2921 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2922 return false;
2923 }
2924
2925 switch (pname)
2926 {
2927 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2928 if (value < 0.0f)
2929 {
2930 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2931 return false;
2932 }
2933 break;
2934 case GL_PATH_END_CAPS_CHROMIUM:
2935 switch (static_cast<GLenum>(value))
2936 {
2937 case GL_FLAT_CHROMIUM:
2938 case GL_SQUARE_CHROMIUM:
2939 case GL_ROUND_CHROMIUM:
2940 break;
2941 default:
2942 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2943 return false;
2944 }
2945 break;
2946 case GL_PATH_JOIN_STYLE_CHROMIUM:
2947 switch (static_cast<GLenum>(value))
2948 {
2949 case GL_MITER_REVERT_CHROMIUM:
2950 case GL_BEVEL_CHROMIUM:
2951 case GL_ROUND_CHROMIUM:
2952 break;
2953 default:
2954 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2955 return false;
2956 }
2957 case GL_PATH_MITER_LIMIT_CHROMIUM:
2958 if (value < 0.0f)
2959 {
2960 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2961 return false;
2962 }
2963 break;
2964
2965 case GL_PATH_STROKE_BOUND_CHROMIUM:
2966 // no errors, only clamping.
2967 break;
2968
2969 default:
2970 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2971 return false;
2972 }
2973 return true;
2974}
2975
2976bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2977{
2978 if (!context->getExtensions().pathRendering)
2979 {
2980 context->handleError(
2981 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2982 return false;
2983 }
2984
2985 if (!context->hasPath(path))
2986 {
2987 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2988 return false;
2989 }
2990 if (!value)
2991 {
2992 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2993 return false;
2994 }
2995
2996 switch (pname)
2997 {
2998 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2999 case GL_PATH_END_CAPS_CHROMIUM:
3000 case GL_PATH_JOIN_STYLE_CHROMIUM:
3001 case GL_PATH_MITER_LIMIT_CHROMIUM:
3002 case GL_PATH_STROKE_BOUND_CHROMIUM:
3003 break;
3004
3005 default:
3006 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
3007 return false;
3008 }
3009
3010 return true;
3011}
3012
3013bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3014{
3015 if (!context->getExtensions().pathRendering)
3016 {
3017 context->handleError(
3018 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3019 return false;
3020 }
3021
3022 switch (func)
3023 {
3024 case GL_NEVER:
3025 case GL_ALWAYS:
3026 case GL_LESS:
3027 case GL_LEQUAL:
3028 case GL_EQUAL:
3029 case GL_GEQUAL:
3030 case GL_GREATER:
3031 case GL_NOTEQUAL:
3032 break;
3033 default:
3034 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
3035 return false;
3036 }
3037
3038 return true;
3039}
3040
3041// Note that the spec specifies that for the path drawing commands
3042// if the path object is not an existing path object the command
3043// does nothing and no error is generated.
3044// However if the path object exists but has not been specified any
3045// commands then an error is generated.
3046
3047bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3048{
3049 if (!context->getExtensions().pathRendering)
3050 {
3051 context->handleError(
3052 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3053 return false;
3054 }
3055 if (context->hasPath(path) && !context->hasPathData(path))
3056 {
3057 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3058 return false;
3059 }
3060
3061 switch (fillMode)
3062 {
3063 case GL_COUNT_UP_CHROMIUM:
3064 case GL_COUNT_DOWN_CHROMIUM:
3065 break;
3066 default:
3067 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3068 return false;
3069 }
3070
3071 if (!isPow2(mask + 1))
3072 {
3073 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3074 return false;
3075 }
3076
3077 return true;
3078}
3079
3080bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3081{
3082 if (!context->getExtensions().pathRendering)
3083 {
3084 context->handleError(
3085 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3086 return false;
3087 }
3088 if (context->hasPath(path) && !context->hasPathData(path))
3089 {
3090 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
3091 return false;
3092 }
3093
3094 return true;
3095}
3096
3097bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3098{
3099 if (!context->getExtensions().pathRendering)
3100 {
3101 context->handleError(
3102 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3103 return false;
3104 }
3105 if (context->hasPath(path) && !context->hasPathData(path))
3106 {
3107 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3108 return false;
3109 }
3110
3111 switch (coverMode)
3112 {
3113 case GL_CONVEX_HULL_CHROMIUM:
3114 case GL_BOUNDING_BOX_CHROMIUM:
3115 break;
3116 default:
3117 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3118 return false;
3119 }
3120 return true;
3121}
3122
3123bool ValidateStencilThenCoverFillPath(Context *context,
3124 GLuint path,
3125 GLenum fillMode,
3126 GLuint mask,
3127 GLenum coverMode)
3128{
3129 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3130 ValidateCoverPath(context, path, coverMode);
3131}
3132
3133bool ValidateStencilThenCoverStrokePath(Context *context,
3134 GLuint path,
3135 GLint reference,
3136 GLuint mask,
3137 GLenum coverMode)
3138{
3139 return ValidateStencilStrokePath(context, path, reference, mask) &&
3140 ValidateCoverPath(context, path, coverMode);
3141}
3142
3143bool ValidateIsPath(Context *context)
3144{
3145 if (!context->getExtensions().pathRendering)
3146 {
3147 context->handleError(
3148 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3149 return false;
3150 }
3151 return true;
3152}
3153
Sami Väisänend59ca052016-06-21 16:10:00 +03003154bool ValidateCoverFillPathInstanced(Context *context,
3155 GLsizei numPaths,
3156 GLenum pathNameType,
3157 const void *paths,
3158 GLuint pathBase,
3159 GLenum coverMode,
3160 GLenum transformType,
3161 const GLfloat *transformValues)
3162{
3163 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3164 transformType, transformValues))
3165 return false;
3166
3167 switch (coverMode)
3168 {
3169 case GL_CONVEX_HULL_CHROMIUM:
3170 case GL_BOUNDING_BOX_CHROMIUM:
3171 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3172 break;
3173 default:
3174 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3175 return false;
3176 }
3177
3178 return true;
3179}
3180
3181bool ValidateCoverStrokePathInstanced(Context *context,
3182 GLsizei numPaths,
3183 GLenum pathNameType,
3184 const void *paths,
3185 GLuint pathBase,
3186 GLenum coverMode,
3187 GLenum transformType,
3188 const GLfloat *transformValues)
3189{
3190 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3191 transformType, transformValues))
3192 return false;
3193
3194 switch (coverMode)
3195 {
3196 case GL_CONVEX_HULL_CHROMIUM:
3197 case GL_BOUNDING_BOX_CHROMIUM:
3198 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3199 break;
3200 default:
3201 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3202 return false;
3203 }
3204
3205 return true;
3206}
3207
3208bool ValidateStencilFillPathInstanced(Context *context,
3209 GLsizei numPaths,
3210 GLenum pathNameType,
3211 const void *paths,
3212 GLuint pathBase,
3213 GLenum fillMode,
3214 GLuint mask,
3215 GLenum transformType,
3216 const GLfloat *transformValues)
3217{
3218
3219 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3220 transformType, transformValues))
3221 return false;
3222
3223 switch (fillMode)
3224 {
3225 case GL_COUNT_UP_CHROMIUM:
3226 case GL_COUNT_DOWN_CHROMIUM:
3227 break;
3228 default:
3229 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3230 return false;
3231 }
3232 if (!isPow2(mask + 1))
3233 {
3234 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3235 return false;
3236 }
3237 return true;
3238}
3239
3240bool ValidateStencilStrokePathInstanced(Context *context,
3241 GLsizei numPaths,
3242 GLenum pathNameType,
3243 const void *paths,
3244 GLuint pathBase,
3245 GLint reference,
3246 GLuint mask,
3247 GLenum transformType,
3248 const GLfloat *transformValues)
3249{
3250 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3251 transformType, transformValues))
3252 return false;
3253
3254 // no more validation here.
3255
3256 return true;
3257}
3258
3259bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3260 GLsizei numPaths,
3261 GLenum pathNameType,
3262 const void *paths,
3263 GLuint pathBase,
3264 GLenum fillMode,
3265 GLuint mask,
3266 GLenum coverMode,
3267 GLenum transformType,
3268 const GLfloat *transformValues)
3269{
3270 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3271 transformType, transformValues))
3272 return false;
3273
3274 switch (coverMode)
3275 {
3276 case GL_CONVEX_HULL_CHROMIUM:
3277 case GL_BOUNDING_BOX_CHROMIUM:
3278 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3279 break;
3280 default:
3281 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3282 return false;
3283 }
3284
3285 switch (fillMode)
3286 {
3287 case GL_COUNT_UP_CHROMIUM:
3288 case GL_COUNT_DOWN_CHROMIUM:
3289 break;
3290 default:
3291 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3292 return false;
3293 }
3294 if (!isPow2(mask + 1))
3295 {
3296 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3297 return false;
3298 }
3299
3300 return true;
3301}
3302
3303bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3304 GLsizei numPaths,
3305 GLenum pathNameType,
3306 const void *paths,
3307 GLuint pathBase,
3308 GLint reference,
3309 GLuint mask,
3310 GLenum coverMode,
3311 GLenum transformType,
3312 const GLfloat *transformValues)
3313{
3314 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3315 transformType, transformValues))
3316 return false;
3317
3318 switch (coverMode)
3319 {
3320 case GL_CONVEX_HULL_CHROMIUM:
3321 case GL_BOUNDING_BOX_CHROMIUM:
3322 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3323 break;
3324 default:
3325 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3326 return false;
3327 }
3328
3329 return true;
3330}
3331
Sami Väisänen46eaa942016-06-29 10:26:37 +03003332bool ValidateBindFragmentInputLocation(Context *context,
3333 GLuint program,
3334 GLint location,
3335 const GLchar *name)
3336{
3337 if (!context->getExtensions().pathRendering)
3338 {
3339 context->handleError(
3340 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3341 return false;
3342 }
3343
3344 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3345 if (location >= MaxLocation)
3346 {
3347 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3348 return false;
3349 }
3350
3351 const auto *programObject = context->getProgram(program);
3352 if (!programObject)
3353 {
3354 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3355 return false;
3356 }
3357
3358 if (!name)
3359 {
3360 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3361 return false;
3362 }
3363
3364 if (angle::BeginsWith(name, "gl_"))
3365 {
3366 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3367 return false;
3368 }
3369
3370 return true;
3371}
3372
3373bool ValidateProgramPathFragmentInputGen(Context *context,
3374 GLuint program,
3375 GLint location,
3376 GLenum genMode,
3377 GLint components,
3378 const GLfloat *coeffs)
3379{
3380 if (!context->getExtensions().pathRendering)
3381 {
3382 context->handleError(
3383 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3384 return false;
3385 }
3386
3387 const auto *programObject = context->getProgram(program);
3388 if (!programObject || programObject->isFlaggedForDeletion())
3389 {
3390 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3391 return false;
3392 }
3393
3394 if (!programObject->isLinked())
3395 {
3396 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3397 return false;
3398 }
3399
3400 switch (genMode)
3401 {
3402 case GL_NONE:
3403 if (components != 0)
3404 {
3405 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3406 return false;
3407 }
3408 break;
3409
3410 case GL_OBJECT_LINEAR_CHROMIUM:
3411 case GL_EYE_LINEAR_CHROMIUM:
3412 case GL_CONSTANT_CHROMIUM:
3413 if (components < 1 || components > 4)
3414 {
3415 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3416 return false;
3417 }
3418 if (!coeffs)
3419 {
3420 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3421 return false;
3422 }
3423 break;
3424
3425 default:
3426 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3427 return false;
3428 }
3429
3430 // If the location is -1 then the command is silently ignored
3431 // and no further validation is needed.
3432 if (location == -1)
3433 return true;
3434
3435 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3436
3437 if (!binding.valid)
3438 {
3439 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3440 return false;
3441 }
3442
3443 if (binding.type != GL_NONE)
3444 {
3445 GLint expectedComponents = 0;
3446 switch (binding.type)
3447 {
3448 case GL_FLOAT:
3449 expectedComponents = 1;
3450 break;
3451 case GL_FLOAT_VEC2:
3452 expectedComponents = 2;
3453 break;
3454 case GL_FLOAT_VEC3:
3455 expectedComponents = 3;
3456 break;
3457 case GL_FLOAT_VEC4:
3458 expectedComponents = 4;
3459 break;
3460 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003461 context->handleError(
3462 Error(GL_INVALID_OPERATION,
3463 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003464 return false;
3465 }
3466 if (expectedComponents != components && genMode != GL_NONE)
3467 {
3468 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3469 return false;
3470 }
3471 }
3472 return true;
3473}
3474
Geoff Lang97073d12016-04-20 10:42:34 -07003475bool ValidateCopyTextureCHROMIUM(Context *context,
3476 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003477 GLint sourceLevel,
3478 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003479 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003480 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003481 GLint internalFormat,
3482 GLenum destType,
3483 GLboolean unpackFlipY,
3484 GLboolean unpackPremultiplyAlpha,
3485 GLboolean unpackUnmultiplyAlpha)
3486{
3487 if (!context->getExtensions().copyTexture)
3488 {
3489 context->handleError(
3490 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3491 return false;
3492 }
3493
Geoff Lang4f0e0032017-05-01 16:04:35 -04003494 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003495 if (source == nullptr)
3496 {
3497 context->handleError(
3498 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3499 return false;
3500 }
3501
3502 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3503 {
3504 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3505 return false;
3506 }
3507
3508 GLenum sourceTarget = source->getTarget();
3509 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003510
3511 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003512 {
Geoff Lang4f0e0032017-05-01 16:04:35 -04003513 context->handleError(Error(GL_INVALID_VALUE, "Source texture level is not valid."));
Geoff Lang97073d12016-04-20 10:42:34 -07003514 return false;
3515 }
3516
Geoff Lang4f0e0032017-05-01 16:04:35 -04003517 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3518 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3519 if (sourceWidth == 0 || sourceHeight == 0)
3520 {
3521 context->handleError(
3522 Error(GL_INVALID_VALUE, "The source level of the source texture must be defined."));
3523 return false;
3524 }
3525
3526 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3527 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003528 {
3529 context->handleError(
3530 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3531 return false;
3532 }
3533
Geoff Lang4f0e0032017-05-01 16:04:35 -04003534 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003535 if (dest == nullptr)
3536 {
3537 context->handleError(
3538 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3539 return false;
3540 }
3541
Geoff Lang4f0e0032017-05-01 16:04:35 -04003542 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003543 {
3544 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3545 return false;
3546 }
3547
Geoff Lang4f0e0032017-05-01 16:04:35 -04003548 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3549 sourceHeight))
3550 {
3551 context->handleError(Error(GL_INVALID_VALUE, "Destination texture level is not valid."));
3552 return false;
3553 }
3554
Geoff Lang97073d12016-04-20 10:42:34 -07003555 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3556 {
3557 context->handleError(
3558 Error(GL_INVALID_OPERATION,
3559 "Destination internal format and type combination is not valid."));
3560 return false;
3561 }
3562
Geoff Lang4f0e0032017-05-01 16:04:35 -04003563 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3564 {
3565 context->handleError(Error(
3566 GL_INVALID_VALUE, "Destination width and height must be equal for cube map textures."));
3567 return false;
3568 }
3569
Geoff Lang97073d12016-04-20 10:42:34 -07003570 if (dest->getImmutableFormat())
3571 {
3572 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3573 return false;
3574 }
3575
3576 return true;
3577}
3578
3579bool ValidateCopySubTextureCHROMIUM(Context *context,
3580 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003581 GLint sourceLevel,
3582 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003583 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003584 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003585 GLint xoffset,
3586 GLint yoffset,
3587 GLint x,
3588 GLint y,
3589 GLsizei width,
3590 GLsizei height,
3591 GLboolean unpackFlipY,
3592 GLboolean unpackPremultiplyAlpha,
3593 GLboolean unpackUnmultiplyAlpha)
3594{
3595 if (!context->getExtensions().copyTexture)
3596 {
3597 context->handleError(
3598 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3599 return false;
3600 }
3601
Geoff Lang4f0e0032017-05-01 16:04:35 -04003602 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003603 if (source == nullptr)
3604 {
3605 context->handleError(
3606 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3607 return false;
3608 }
3609
3610 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3611 {
3612 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3613 return false;
3614 }
3615
3616 GLenum sourceTarget = source->getTarget();
3617 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003618
3619 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3620 {
3621 context->handleError(Error(GL_INVALID_VALUE, "Source texture level is not valid."));
3622 return false;
3623 }
3624
3625 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3626 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003627 {
3628 context->handleError(
Geoff Lang4f0e0032017-05-01 16:04:35 -04003629 Error(GL_INVALID_VALUE, "The source level of the source texture must be defined."));
Geoff Lang97073d12016-04-20 10:42:34 -07003630 return false;
3631 }
3632
3633 if (x < 0 || y < 0)
3634 {
3635 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3636 return false;
3637 }
3638
3639 if (width < 0 || height < 0)
3640 {
3641 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3642 return false;
3643 }
3644
Geoff Lang4f0e0032017-05-01 16:04:35 -04003645 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3646 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003647 {
3648 context->handleError(
3649 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3650 return false;
3651 }
3652
Geoff Lang4f0e0032017-05-01 16:04:35 -04003653 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3654 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003655 {
3656 context->handleError(
3657 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3658 return false;
3659 }
3660
Geoff Lang4f0e0032017-05-01 16:04:35 -04003661 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003662 if (dest == nullptr)
3663 {
3664 context->handleError(
3665 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3666 return false;
3667 }
3668
Geoff Lang4f0e0032017-05-01 16:04:35 -04003669 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003670 {
3671 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3672 return false;
3673 }
3674
Geoff Lang4f0e0032017-05-01 16:04:35 -04003675 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003676 {
Geoff Lang4f0e0032017-05-01 16:04:35 -04003677 context->handleError(Error(GL_INVALID_VALUE, "Destination texture level is not valid."));
Geoff Lang97073d12016-04-20 10:42:34 -07003678 return false;
3679 }
3680
Geoff Lang4f0e0032017-05-01 16:04:35 -04003681 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3682 {
3683 context->handleError(Error(
3684 GL_INVALID_VALUE, "The destination level of the destination texture must be defined."));
3685 return false;
3686 }
3687
3688 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3689 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003690 {
3691 context->handleError(
3692 Error(GL_INVALID_OPERATION,
3693 "Destination internal format and type combination is not valid."));
3694 return false;
3695 }
3696
3697 if (xoffset < 0 || yoffset < 0)
3698 {
3699 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3700 return false;
3701 }
3702
Geoff Lang4f0e0032017-05-01 16:04:35 -04003703 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3704 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003705 {
3706 context->handleError(
3707 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3708 return false;
3709 }
3710
3711 return true;
3712}
3713
Geoff Lang47110bf2016-04-20 11:13:22 -07003714bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3715{
3716 if (!context->getExtensions().copyCompressedTexture)
3717 {
3718 context->handleError(Error(GL_INVALID_OPERATION,
3719 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3720 return false;
3721 }
3722
3723 const gl::Texture *source = context->getTexture(sourceId);
3724 if (source == nullptr)
3725 {
3726 context->handleError(
3727 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3728 return false;
3729 }
3730
3731 if (source->getTarget() != GL_TEXTURE_2D)
3732 {
3733 context->handleError(
3734 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3735 return false;
3736 }
3737
3738 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3739 {
3740 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3741 return false;
3742 }
3743
3744 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3745 if (!sourceFormat.info->compressed)
3746 {
3747 context->handleError(
3748 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3749 return false;
3750 }
3751
3752 const gl::Texture *dest = context->getTexture(destId);
3753 if (dest == nullptr)
3754 {
3755 context->handleError(
3756 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3757 return false;
3758 }
3759
3760 if (dest->getTarget() != GL_TEXTURE_2D)
3761 {
3762 context->handleError(
3763 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3764 return false;
3765 }
3766
3767 if (dest->getImmutableFormat())
3768 {
3769 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3770 return false;
3771 }
3772
3773 return true;
3774}
3775
Martin Radev4c4c8e72016-08-04 12:25:34 +03003776bool ValidateCreateShader(Context *context, GLenum type)
3777{
3778 switch (type)
3779 {
3780 case GL_VERTEX_SHADER:
3781 case GL_FRAGMENT_SHADER:
3782 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003783
Martin Radev4c4c8e72016-08-04 12:25:34 +03003784 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003785 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003786 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003787 context->handleError(
3788 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3789 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003790 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003791 break;
3792
Martin Radev4c4c8e72016-08-04 12:25:34 +03003793 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003794 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003795 return false;
3796 }
Jamie Madill29639852016-09-02 15:00:09 -04003797
3798 return true;
3799}
3800
3801bool ValidateBufferData(ValidationContext *context,
3802 GLenum target,
3803 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003804 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003805 GLenum usage)
3806{
3807 if (size < 0)
3808 {
3809 context->handleError(Error(GL_INVALID_VALUE));
3810 return false;
3811 }
3812
3813 switch (usage)
3814 {
3815 case GL_STREAM_DRAW:
3816 case GL_STATIC_DRAW:
3817 case GL_DYNAMIC_DRAW:
3818 break;
3819
3820 case GL_STREAM_READ:
3821 case GL_STREAM_COPY:
3822 case GL_STATIC_READ:
3823 case GL_STATIC_COPY:
3824 case GL_DYNAMIC_READ:
3825 case GL_DYNAMIC_COPY:
3826 if (context->getClientMajorVersion() < 3)
3827 {
3828 context->handleError(Error(GL_INVALID_ENUM));
3829 return false;
3830 }
3831 break;
3832
3833 default:
3834 context->handleError(Error(GL_INVALID_ENUM));
3835 return false;
3836 }
3837
3838 if (!ValidBufferTarget(context, target))
3839 {
3840 context->handleError(Error(GL_INVALID_ENUM));
3841 return false;
3842 }
3843
3844 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3845
3846 if (!buffer)
3847 {
3848 context->handleError(Error(GL_INVALID_OPERATION));
3849 return false;
3850 }
3851
3852 return true;
3853}
3854
3855bool ValidateBufferSubData(ValidationContext *context,
3856 GLenum target,
3857 GLintptr offset,
3858 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003859 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003860{
3861 if (size < 0 || offset < 0)
3862 {
3863 context->handleError(Error(GL_INVALID_VALUE));
3864 return false;
3865 }
3866
3867 if (!ValidBufferTarget(context, target))
3868 {
3869 context->handleError(Error(GL_INVALID_ENUM));
3870 return false;
3871 }
3872
3873 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3874
3875 if (!buffer)
3876 {
3877 context->handleError(Error(GL_INVALID_OPERATION));
3878 return false;
3879 }
3880
3881 if (buffer->isMapped())
3882 {
3883 context->handleError(Error(GL_INVALID_OPERATION));
3884 return false;
3885 }
3886
3887 // Check for possible overflow of size + offset
3888 angle::CheckedNumeric<size_t> checkedSize(size);
3889 checkedSize += offset;
3890 if (!checkedSize.IsValid())
3891 {
3892 context->handleError(Error(GL_OUT_OF_MEMORY));
3893 return false;
3894 }
3895
3896 if (size + offset > buffer->getSize())
3897 {
3898 context->handleError(Error(GL_INVALID_VALUE));
3899 return false;
3900 }
3901
Martin Radev4c4c8e72016-08-04 12:25:34 +03003902 return true;
3903}
3904
Geoff Langc339c4e2016-11-29 10:37:36 -05003905bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003906{
Geoff Langc339c4e2016-11-29 10:37:36 -05003907 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003908 {
3909 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003910 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003911 return false;
3912 }
3913
3914 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3915 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003916 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003917 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003918 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003919 return false;
3920 }
3921
3922 return true;
3923}
3924
Jamie Madillef300b12016-10-07 15:12:09 -04003925bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3926{
3927 if (texture < GL_TEXTURE0 ||
3928 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3929 {
3930 context->handleError(Error(GL_INVALID_ENUM));
3931 return false;
3932 }
3933
3934 return true;
3935}
3936
3937bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3938{
3939 Program *programObject = GetValidProgram(context, program);
3940 if (!programObject)
3941 {
3942 return false;
3943 }
3944
3945 Shader *shaderObject = GetValidShader(context, shader);
3946 if (!shaderObject)
3947 {
3948 return false;
3949 }
3950
3951 switch (shaderObject->getType())
3952 {
3953 case GL_VERTEX_SHADER:
3954 {
3955 if (programObject->getAttachedVertexShader())
3956 {
3957 context->handleError(Error(GL_INVALID_OPERATION));
3958 return false;
3959 }
3960 break;
3961 }
3962 case GL_FRAGMENT_SHADER:
3963 {
3964 if (programObject->getAttachedFragmentShader())
3965 {
3966 context->handleError(Error(GL_INVALID_OPERATION));
3967 return false;
3968 }
3969 break;
3970 }
3971 case GL_COMPUTE_SHADER:
3972 {
3973 if (programObject->getAttachedComputeShader())
3974 {
3975 context->handleError(Error(GL_INVALID_OPERATION));
3976 return false;
3977 }
3978 break;
3979 }
3980 default:
3981 UNREACHABLE();
3982 break;
3983 }
3984
3985 return true;
3986}
3987
Jamie Madill01a80ee2016-11-07 12:06:18 -05003988bool ValidateBindAttribLocation(ValidationContext *context,
3989 GLuint program,
3990 GLuint index,
3991 const GLchar *name)
3992{
3993 if (index >= MAX_VERTEX_ATTRIBS)
3994 {
3995 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3996 return false;
3997 }
3998
3999 if (strncmp(name, "gl_", 3) == 0)
4000 {
4001 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
4002 return false;
4003 }
4004
4005 return GetValidProgram(context, program) != nullptr;
4006}
4007
4008bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4009{
4010 if (!ValidBufferTarget(context, target))
4011 {
4012 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
4013 return false;
4014 }
4015
4016 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4017 !context->isBufferGenerated(buffer))
4018 {
4019 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
4020 return false;
4021 }
4022
4023 return true;
4024}
4025
4026bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4027{
4028 if (!ValidFramebufferTarget(target))
4029 {
4030 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4031 return false;
4032 }
4033
4034 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4035 !context->isFramebufferGenerated(framebuffer))
4036 {
4037 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
4038 return false;
4039 }
4040
4041 return true;
4042}
4043
4044bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4045{
4046 if (target != GL_RENDERBUFFER)
4047 {
4048 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
4049 return false;
4050 }
4051
4052 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4053 !context->isRenderbufferGenerated(renderbuffer))
4054 {
4055 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
4056 return false;
4057 }
4058
4059 return true;
4060}
4061
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004062static bool ValidBlendEquationMode(GLenum mode)
4063{
4064 switch (mode)
4065 {
4066 case GL_FUNC_ADD:
4067 case GL_FUNC_SUBTRACT:
4068 case GL_FUNC_REVERSE_SUBTRACT:
4069 case GL_MIN:
4070 case GL_MAX:
4071 return true;
4072
4073 default:
4074 return false;
4075 }
4076}
4077
Jamie Madillc1d770e2017-04-13 17:31:24 -04004078bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004079 GLfloat red,
4080 GLfloat green,
4081 GLfloat blue,
4082 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004083{
4084 return true;
4085}
4086
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004087bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4088{
4089 if (!ValidBlendEquationMode(mode))
4090 {
4091 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
4092 return false;
4093 }
4094
4095 return true;
4096}
4097
4098bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4099{
4100 if (!ValidBlendEquationMode(modeRGB))
4101 {
4102 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
4103 return false;
4104 }
4105
4106 if (!ValidBlendEquationMode(modeAlpha))
4107 {
4108 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
4109 return false;
4110 }
4111
4112 return true;
4113}
4114
4115bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4116{
4117 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4118}
4119
4120static bool ValidSrcBlendFunc(GLenum srcBlend)
4121{
4122 switch (srcBlend)
4123 {
4124 case GL_ZERO:
4125 case GL_ONE:
4126 case GL_SRC_COLOR:
4127 case GL_ONE_MINUS_SRC_COLOR:
4128 case GL_DST_COLOR:
4129 case GL_ONE_MINUS_DST_COLOR:
4130 case GL_SRC_ALPHA:
4131 case GL_ONE_MINUS_SRC_ALPHA:
4132 case GL_DST_ALPHA:
4133 case GL_ONE_MINUS_DST_ALPHA:
4134 case GL_CONSTANT_COLOR:
4135 case GL_ONE_MINUS_CONSTANT_COLOR:
4136 case GL_CONSTANT_ALPHA:
4137 case GL_ONE_MINUS_CONSTANT_ALPHA:
4138 case GL_SRC_ALPHA_SATURATE:
4139 return true;
4140
4141 default:
4142 return false;
4143 }
4144}
4145
4146static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4147{
4148 switch (dstBlend)
4149 {
4150 case GL_ZERO:
4151 case GL_ONE:
4152 case GL_SRC_COLOR:
4153 case GL_ONE_MINUS_SRC_COLOR:
4154 case GL_DST_COLOR:
4155 case GL_ONE_MINUS_DST_COLOR:
4156 case GL_SRC_ALPHA:
4157 case GL_ONE_MINUS_SRC_ALPHA:
4158 case GL_DST_ALPHA:
4159 case GL_ONE_MINUS_DST_ALPHA:
4160 case GL_CONSTANT_COLOR:
4161 case GL_ONE_MINUS_CONSTANT_COLOR:
4162 case GL_CONSTANT_ALPHA:
4163 case GL_ONE_MINUS_CONSTANT_ALPHA:
4164 return true;
4165
4166 case GL_SRC_ALPHA_SATURATE:
4167 return (contextMajorVersion >= 3);
4168
4169 default:
4170 return false;
4171 }
4172}
4173
4174bool ValidateBlendFuncSeparate(ValidationContext *context,
4175 GLenum srcRGB,
4176 GLenum dstRGB,
4177 GLenum srcAlpha,
4178 GLenum dstAlpha)
4179{
4180 if (!ValidSrcBlendFunc(srcRGB))
4181 {
4182 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4183 return false;
4184 }
4185
4186 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4187 {
4188 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4189 return false;
4190 }
4191
4192 if (!ValidSrcBlendFunc(srcAlpha))
4193 {
4194 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4195 return false;
4196 }
4197
4198 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4199 {
4200 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4201 return false;
4202 }
4203
Frank Henigman146e8a12017-03-02 23:22:37 -05004204 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4205 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004206 {
4207 bool constantColorUsed =
4208 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4209 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4210
4211 bool constantAlphaUsed =
4212 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4213 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4214
4215 if (constantColorUsed && constantAlphaUsed)
4216 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004217 const char *msg;
4218 if (context->getExtensions().webglCompatibility)
4219 {
4220 msg =
4221 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4222 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4223 }
4224 else
4225 {
4226 msg =
4227 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4228 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4229 "implementation.";
4230 ERR() << msg;
4231 }
4232 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004233 return false;
4234 }
4235 }
4236
4237 return true;
4238}
4239
Geoff Langc339c4e2016-11-29 10:37:36 -05004240bool ValidateGetString(Context *context, GLenum name)
4241{
4242 switch (name)
4243 {
4244 case GL_VENDOR:
4245 case GL_RENDERER:
4246 case GL_VERSION:
4247 case GL_SHADING_LANGUAGE_VERSION:
4248 case GL_EXTENSIONS:
4249 break;
4250
4251 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4252 if (!context->getExtensions().requestExtension)
4253 {
4254 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4255 return false;
4256 }
4257 break;
4258
4259 default:
4260 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4261 return false;
4262 }
4263
4264 return true;
4265}
4266
Geoff Lang47c48082016-12-07 15:38:13 -05004267bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4268{
4269 if (width <= 0.0f || isNaN(width))
4270 {
4271 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
4272 return false;
4273 }
4274
4275 return true;
4276}
4277
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004278bool ValidateVertexAttribPointer(ValidationContext *context,
4279 GLuint index,
4280 GLint size,
4281 GLenum type,
4282 GLboolean normalized,
4283 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004284 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004285{
Shao80957d92017-02-20 21:25:59 +08004286 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004287 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004288 return false;
4289 }
4290
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004291 if (stride < 0)
4292 {
Shao80957d92017-02-20 21:25:59 +08004293 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004294 return false;
4295 }
4296
Shao80957d92017-02-20 21:25:59 +08004297 const Caps &caps = context->getCaps();
4298 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004299 {
Shao80957d92017-02-20 21:25:59 +08004300 if (stride > caps.maxVertexAttribStride)
4301 {
4302 context->handleError(
4303 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
4304 return false;
4305 }
4306
4307 if (index >= caps.maxVertexAttribBindings)
4308 {
4309 context->handleError(
4310 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
4311 return false;
4312 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004313 }
4314
4315 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4316 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4317 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4318 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004319 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4320 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004321 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004322 {
4323 context->handleError(
4324 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08004325 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004326 return false;
4327 }
4328
4329 if (context->getExtensions().webglCompatibility)
4330 {
4331 // WebGL 1.0 [Section 6.14] Fixed point support
4332 // The WebGL API does not support the GL_FIXED data type.
4333 if (type == GL_FIXED)
4334 {
4335 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4336 return false;
4337 }
4338
Geoff Lang2d62ab72017-03-23 16:54:40 -04004339 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004340 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004341 return false;
4342 }
4343 }
4344
4345 return true;
4346}
4347
Jamie Madill876429b2017-04-20 15:46:24 -04004348bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004349{
4350 if (context->getExtensions().webglCompatibility && zNear > zFar)
4351 {
4352 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4353 return false;
4354 }
4355
4356 return true;
4357}
4358
Jamie Madille8fb6402017-02-14 17:56:40 -05004359bool ValidateRenderbufferStorage(ValidationContext *context,
4360 GLenum target,
4361 GLenum internalformat,
4362 GLsizei width,
4363 GLsizei height)
4364{
4365 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4366 height);
4367}
4368
4369bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4370 GLenum target,
4371 GLsizei samples,
4372 GLenum internalformat,
4373 GLsizei width,
4374 GLsizei height)
4375{
4376 if (!context->getExtensions().framebufferMultisample)
4377 {
4378 context->handleError(
4379 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4380 return false;
4381 }
4382
4383 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4384 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4385 // generated.
4386 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4387 {
4388 context->handleError(Error(GL_INVALID_VALUE));
4389 return false;
4390 }
4391
4392 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4393 // the specified storage. This is different than ES 3.0 in which a sample number higher
4394 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4395 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4396 if (context->getClientMajorVersion() >= 3)
4397 {
4398 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4399 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4400 {
4401 context->handleError(Error(GL_OUT_OF_MEMORY));
4402 return false;
4403 }
4404 }
4405
4406 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4407 width, height);
4408}
4409
Jamie Madillc1d770e2017-04-13 17:31:24 -04004410bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4411{
4412 if (!ValidFramebufferTarget(target))
4413 {
4414 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4415 return false;
4416 }
4417
4418 return true;
4419}
4420
4421bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004422 GLfloat red,
4423 GLfloat green,
4424 GLfloat blue,
4425 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004426{
4427 return true;
4428}
4429
Jamie Madill876429b2017-04-20 15:46:24 -04004430bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004431{
4432 return true;
4433}
4434
4435bool ValidateClearStencil(ValidationContext *context, GLint s)
4436{
4437 return true;
4438}
4439
4440bool ValidateColorMask(ValidationContext *context,
4441 GLboolean red,
4442 GLboolean green,
4443 GLboolean blue,
4444 GLboolean alpha)
4445{
4446 return true;
4447}
4448
4449bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4450{
4451 return true;
4452}
4453
4454bool ValidateCreateProgram(ValidationContext *context)
4455{
4456 return true;
4457}
4458
4459bool ValidateCullFace(ValidationContext *context, GLenum mode)
4460{
4461 switch (mode)
4462 {
4463 case GL_FRONT:
4464 case GL_BACK:
4465 case GL_FRONT_AND_BACK:
4466 break;
4467
4468 default:
4469 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
4476bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4477{
4478 if (program == 0)
4479 {
4480 return false;
4481 }
4482
4483 if (!context->getProgram(program))
4484 {
4485 if (context->getShader(program))
4486 {
4487 context->handleError(
4488 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
4489 return false;
4490 }
4491 else
4492 {
4493 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
4494 return false;
4495 }
4496 }
4497
4498 return true;
4499}
4500
4501bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4502{
4503 if (shader == 0)
4504 {
4505 return false;
4506 }
4507
4508 if (!context->getShader(shader))
4509 {
4510 if (context->getProgram(shader))
4511 {
4512 context->handleError(
4513 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
4514 return false;
4515 }
4516 else
4517 {
4518 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4519 return false;
4520 }
4521 }
4522
4523 return true;
4524}
4525
4526bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4527{
4528 switch (func)
4529 {
4530 case GL_NEVER:
4531 case GL_ALWAYS:
4532 case GL_LESS:
4533 case GL_LEQUAL:
4534 case GL_EQUAL:
4535 case GL_GREATER:
4536 case GL_GEQUAL:
4537 case GL_NOTEQUAL:
4538 break;
4539
4540 default:
4541 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4542 return false;
4543 }
4544
4545 return true;
4546}
4547
4548bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4549{
4550 return true;
4551}
4552
4553bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4554{
4555 Program *programObject = GetValidProgram(context, program);
4556 if (!programObject)
4557 {
4558 return false;
4559 }
4560
4561 Shader *shaderObject = GetValidShader(context, shader);
4562 if (!shaderObject)
4563 {
4564 return false;
4565 }
4566
4567 const Shader *attachedShader = nullptr;
4568
4569 switch (shaderObject->getType())
4570 {
4571 case GL_VERTEX_SHADER:
4572 {
4573 attachedShader = programObject->getAttachedVertexShader();
4574 break;
4575 }
4576 case GL_FRAGMENT_SHADER:
4577 {
4578 attachedShader = programObject->getAttachedFragmentShader();
4579 break;
4580 }
4581 case GL_COMPUTE_SHADER:
4582 {
4583 attachedShader = programObject->getAttachedComputeShader();
4584 break;
4585 }
4586 default:
4587 UNREACHABLE();
4588 return false;
4589 }
4590
4591 if (attachedShader != shaderObject)
4592 {
4593 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4594 return false;
4595 }
4596
4597 return true;
4598}
4599
4600bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4601{
4602 if (index >= MAX_VERTEX_ATTRIBS)
4603 {
4604 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4605 return false;
4606 }
4607
4608 return true;
4609}
4610
4611bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4612{
4613 if (index >= MAX_VERTEX_ATTRIBS)
4614 {
4615 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4616 return false;
4617 }
4618
4619 return true;
4620}
4621
4622bool ValidateFinish(ValidationContext *context)
4623{
4624 return true;
4625}
4626
4627bool ValidateFlush(ValidationContext *context)
4628{
4629 return true;
4630}
4631
4632bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4633{
4634 switch (mode)
4635 {
4636 case GL_CW:
4637 case GL_CCW:
4638 break;
4639 default:
4640 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4641 return false;
4642 }
4643
4644 return true;
4645}
4646
4647bool ValidateGetActiveAttrib(ValidationContext *context,
4648 GLuint program,
4649 GLuint index,
4650 GLsizei bufsize,
4651 GLsizei *length,
4652 GLint *size,
4653 GLenum *type,
4654 GLchar *name)
4655{
4656 if (bufsize < 0)
4657 {
4658 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4659 return false;
4660 }
4661
4662 Program *programObject = GetValidProgram(context, program);
4663
4664 if (!programObject)
4665 {
4666 return false;
4667 }
4668
4669 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4670 {
4671 context->handleError(
4672 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4673 return false;
4674 }
4675
4676 return true;
4677}
4678
4679bool ValidateGetActiveUniform(ValidationContext *context,
4680 GLuint program,
4681 GLuint index,
4682 GLsizei bufsize,
4683 GLsizei *length,
4684 GLint *size,
4685 GLenum *type,
4686 GLchar *name)
4687{
4688 if (bufsize < 0)
4689 {
4690 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4691 return false;
4692 }
4693
4694 Program *programObject = GetValidProgram(context, program);
4695
4696 if (!programObject)
4697 {
4698 return false;
4699 }
4700
4701 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4702 {
4703 context->handleError(
4704 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4705 return false;
4706 }
4707
4708 return true;
4709}
4710
4711bool ValidateGetAttachedShaders(ValidationContext *context,
4712 GLuint program,
4713 GLsizei maxcount,
4714 GLsizei *count,
4715 GLuint *shaders)
4716{
4717 if (maxcount < 0)
4718 {
4719 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4720 return false;
4721 }
4722
4723 Program *programObject = GetValidProgram(context, program);
4724
4725 if (!programObject)
4726 {
4727 return false;
4728 }
4729
4730 return true;
4731}
4732
4733bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4734{
4735 Program *programObject = GetValidProgram(context, program);
4736
4737 if (!programObject)
4738 {
4739 return false;
4740 }
4741
4742 if (!programObject->isLinked())
4743 {
4744 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4745 return false;
4746 }
4747
4748 return true;
4749}
4750
4751bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4752{
4753 GLenum nativeType;
4754 unsigned int numParams = 0;
4755 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4756}
4757
4758bool ValidateGetError(ValidationContext *context)
4759{
4760 return true;
4761}
4762
4763bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4764{
4765 GLenum nativeType;
4766 unsigned int numParams = 0;
4767 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4768}
4769
4770bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4771{
4772 GLenum nativeType;
4773 unsigned int numParams = 0;
4774 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4775}
4776
4777bool ValidateGetProgramInfoLog(ValidationContext *context,
4778 GLuint program,
4779 GLsizei bufsize,
4780 GLsizei *length,
4781 GLchar *infolog)
4782{
4783 if (bufsize < 0)
4784 {
4785 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4786 return false;
4787 }
4788
4789 Program *programObject = GetValidProgram(context, program);
4790 if (!programObject)
4791 {
4792 return false;
4793 }
4794
4795 return true;
4796}
4797
4798bool ValidateGetShaderInfoLog(ValidationContext *context,
4799 GLuint shader,
4800 GLsizei bufsize,
4801 GLsizei *length,
4802 GLchar *infolog)
4803{
4804 if (bufsize < 0)
4805 {
4806 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4807 return false;
4808 }
4809
4810 Shader *shaderObject = GetValidShader(context, shader);
4811 if (!shaderObject)
4812 {
4813 return false;
4814 }
4815
4816 return true;
4817}
4818
4819bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4820 GLenum shadertype,
4821 GLenum precisiontype,
4822 GLint *range,
4823 GLint *precision)
4824{
4825 switch (shadertype)
4826 {
4827 case GL_VERTEX_SHADER:
4828 case GL_FRAGMENT_SHADER:
4829 break;
4830 case GL_COMPUTE_SHADER:
4831 context->handleError(
4832 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4833 return false;
4834 default:
4835 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4836 return false;
4837 }
4838
4839 switch (precisiontype)
4840 {
4841 case GL_LOW_FLOAT:
4842 case GL_MEDIUM_FLOAT:
4843 case GL_HIGH_FLOAT:
4844 case GL_LOW_INT:
4845 case GL_MEDIUM_INT:
4846 case GL_HIGH_INT:
4847 break;
4848
4849 default:
4850 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4851 return false;
4852 }
4853
4854 return true;
4855}
4856
4857bool ValidateGetShaderSource(ValidationContext *context,
4858 GLuint shader,
4859 GLsizei bufsize,
4860 GLsizei *length,
4861 GLchar *source)
4862{
4863 if (bufsize < 0)
4864 {
4865 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4866 return false;
4867 }
4868
4869 Shader *shaderObject = GetValidShader(context, shader);
4870 if (!shaderObject)
4871 {
4872 return false;
4873 }
4874
4875 return true;
4876}
4877
4878bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4879{
4880 if (strstr(name, "gl_") == name)
4881 {
4882 return false;
4883 }
4884
4885 Program *programObject = GetValidProgram(context, program);
4886
4887 if (!programObject)
4888 {
4889 return false;
4890 }
4891
4892 if (!programObject->isLinked())
4893 {
4894 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4895 return false;
4896 }
4897
4898 return true;
4899}
4900
4901bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4902{
4903 switch (mode)
4904 {
4905 case GL_FASTEST:
4906 case GL_NICEST:
4907 case GL_DONT_CARE:
4908 break;
4909
4910 default:
4911 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4912 return false;
4913 }
4914
4915 switch (target)
4916 {
4917 case GL_GENERATE_MIPMAP_HINT:
4918 break;
4919
4920 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4921 if (!context->getExtensions().standardDerivatives)
4922 {
4923 context->handleError(
4924 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4925 return false;
4926 }
4927 break;
4928
4929 default:
4930 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4931 return false;
4932 }
4933
4934 return true;
4935}
4936
4937bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4938{
4939 return true;
4940}
4941
4942bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4943{
4944 return true;
4945}
4946
4947bool ValidateIsProgram(ValidationContext *context, GLuint program)
4948{
4949 return true;
4950}
4951
4952bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4953{
4954 return true;
4955}
4956
4957bool ValidateIsShader(ValidationContext *context, GLuint shader)
4958{
4959 return true;
4960}
4961
4962bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4963{
4964 return true;
4965}
4966
4967bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4968{
4969 if (context->getClientMajorVersion() < 3)
4970 {
4971 switch (pname)
4972 {
4973 case GL_UNPACK_IMAGE_HEIGHT:
4974 case GL_UNPACK_SKIP_IMAGES:
4975 context->handleError(Error(GL_INVALID_ENUM));
4976 return false;
4977
4978 case GL_UNPACK_ROW_LENGTH:
4979 case GL_UNPACK_SKIP_ROWS:
4980 case GL_UNPACK_SKIP_PIXELS:
4981 if (!context->getExtensions().unpackSubimage)
4982 {
4983 context->handleError(Error(GL_INVALID_ENUM));
4984 return false;
4985 }
4986 break;
4987
4988 case GL_PACK_ROW_LENGTH:
4989 case GL_PACK_SKIP_ROWS:
4990 case GL_PACK_SKIP_PIXELS:
4991 if (!context->getExtensions().packSubimage)
4992 {
4993 context->handleError(Error(GL_INVALID_ENUM));
4994 return false;
4995 }
4996 break;
4997 }
4998 }
4999
5000 if (param < 0)
5001 {
5002 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
5003 return false;
5004 }
5005
5006 switch (pname)
5007 {
5008 case GL_UNPACK_ALIGNMENT:
5009 if (param != 1 && param != 2 && param != 4 && param != 8)
5010 {
5011 context->handleError(Error(GL_INVALID_VALUE));
5012 return false;
5013 }
5014 break;
5015
5016 case GL_PACK_ALIGNMENT:
5017 if (param != 1 && param != 2 && param != 4 && param != 8)
5018 {
5019 context->handleError(Error(GL_INVALID_VALUE));
5020 return false;
5021 }
5022 break;
5023
5024 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5025 case GL_UNPACK_ROW_LENGTH:
5026 case GL_UNPACK_IMAGE_HEIGHT:
5027 case GL_UNPACK_SKIP_IMAGES:
5028 case GL_UNPACK_SKIP_ROWS:
5029 case GL_UNPACK_SKIP_PIXELS:
5030 case GL_PACK_ROW_LENGTH:
5031 case GL_PACK_SKIP_ROWS:
5032 case GL_PACK_SKIP_PIXELS:
5033 break;
5034
5035 default:
5036 context->handleError(Error(GL_INVALID_ENUM));
5037 return false;
5038 }
5039
5040 return true;
5041}
5042
5043bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5044{
5045 return true;
5046}
5047
5048bool ValidateReleaseShaderCompiler(ValidationContext *context)
5049{
5050 return true;
5051}
5052
Jamie Madill876429b2017-04-20 15:46:24 -04005053bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005054{
5055 return true;
5056}
5057
5058bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5059{
5060 if (width < 0 || height < 0)
5061 {
5062 context->handleError(
5063 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
5064 return false;
5065 }
5066
5067 return true;
5068}
5069
5070bool ValidateShaderBinary(ValidationContext *context,
5071 GLsizei n,
5072 const GLuint *shaders,
5073 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005074 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005075 GLsizei length)
5076{
5077 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5078 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5079 shaderBinaryFormats.end())
5080 {
5081 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
5082 return false;
5083 }
5084
5085 return true;
5086}
5087
5088bool ValidateShaderSource(ValidationContext *context,
5089 GLuint shader,
5090 GLsizei count,
5091 const GLchar *const *string,
5092 const GLint *length)
5093{
5094 if (count < 0)
5095 {
5096 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
5097 return false;
5098 }
5099
5100 Shader *shaderObject = GetValidShader(context, shader);
5101 if (!shaderObject)
5102 {
5103 return false;
5104 }
5105
5106 return true;
5107}
5108
5109bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5110{
5111 if (!IsValidStencilFunc(func))
5112 {
5113 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
5114 return false;
5115 }
5116
5117 return true;
5118}
5119
5120bool ValidateStencilFuncSeparate(ValidationContext *context,
5121 GLenum face,
5122 GLenum func,
5123 GLint ref,
5124 GLuint mask)
5125{
5126 if (!IsValidStencilFace(face))
5127 {
5128 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5129 return false;
5130 }
5131
5132 if (!IsValidStencilFunc(func))
5133 {
5134 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
5135 return false;
5136 }
5137
5138 return true;
5139}
5140
5141bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5142{
5143 return true;
5144}
5145
5146bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5147{
5148 if (!IsValidStencilFace(face))
5149 {
5150 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5151 return false;
5152 }
5153
5154 return true;
5155}
5156
5157bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5158{
5159 if (!IsValidStencilOp(fail))
5160 {
5161 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
5162 return false;
5163 }
5164
5165 if (!IsValidStencilOp(zfail))
5166 {
5167 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
5168 return false;
5169 }
5170
5171 if (!IsValidStencilOp(zpass))
5172 {
5173 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
5174 return false;
5175 }
5176
5177 return true;
5178}
5179
5180bool ValidateStencilOpSeparate(ValidationContext *context,
5181 GLenum face,
5182 GLenum fail,
5183 GLenum zfail,
5184 GLenum zpass)
5185{
5186 if (!IsValidStencilFace(face))
5187 {
5188 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5189 return false;
5190 }
5191
5192 return ValidateStencilOp(context, fail, zfail, zpass);
5193}
5194
5195bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5196{
5197 return ValidateUniform(context, GL_FLOAT, location, 1);
5198}
5199
5200bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5201{
5202 return ValidateUniform(context, GL_FLOAT, location, count);
5203}
5204
Jamie Madillbe849e42017-05-02 15:49:00 -04005205bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5206{
5207 return ValidateUniform1iv(context, location, 1, &x);
5208}
5209
Jamie Madillc1d770e2017-04-13 17:31:24 -04005210bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5211{
5212 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5213}
5214
5215bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5216{
5217 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5218}
5219
5220bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5221{
5222 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5223}
5224
5225bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5226{
5227 return ValidateUniform(context, GL_INT_VEC2, location, count);
5228}
5229
5230bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5231{
5232 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5233}
5234
5235bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5236{
5237 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5238}
5239
5240bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5241{
5242 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5243}
5244
5245bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5246{
5247 return ValidateUniform(context, GL_INT_VEC3, location, count);
5248}
5249
5250bool ValidateUniform4f(ValidationContext *context,
5251 GLint location,
5252 GLfloat x,
5253 GLfloat y,
5254 GLfloat z,
5255 GLfloat w)
5256{
5257 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5258}
5259
5260bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5261{
5262 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5263}
5264
5265bool ValidateUniform4i(ValidationContext *context,
5266 GLint location,
5267 GLint x,
5268 GLint y,
5269 GLint z,
5270 GLint w)
5271{
5272 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5273}
5274
5275bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5276{
5277 return ValidateUniform(context, GL_INT_VEC4, location, count);
5278}
5279
5280bool ValidateUniformMatrix2fv(ValidationContext *context,
5281 GLint location,
5282 GLsizei count,
5283 GLboolean transpose,
5284 const GLfloat *value)
5285{
5286 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5287}
5288
5289bool ValidateUniformMatrix3fv(ValidationContext *context,
5290 GLint location,
5291 GLsizei count,
5292 GLboolean transpose,
5293 const GLfloat *value)
5294{
5295 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5296}
5297
5298bool ValidateUniformMatrix4fv(ValidationContext *context,
5299 GLint location,
5300 GLsizei count,
5301 GLboolean transpose,
5302 const GLfloat *value)
5303{
5304 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5305}
5306
5307bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5308{
5309 Program *programObject = GetValidProgram(context, program);
5310
5311 if (!programObject)
5312 {
5313 return false;
5314 }
5315
5316 return true;
5317}
5318
5319bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5320{
5321 if (index >= MAX_VERTEX_ATTRIBS)
5322 {
5323 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
5324 return false;
5325 }
5326
5327 return true;
5328}
5329
5330bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5331{
5332 return ValidateVertexAttribIndex(context, index);
5333}
5334
5335bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5336{
5337 return ValidateVertexAttribIndex(context, index);
5338}
5339
5340bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5341{
5342 return ValidateVertexAttribIndex(context, index);
5343}
5344
5345bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5346{
5347 return ValidateVertexAttribIndex(context, index);
5348}
5349
5350bool ValidateVertexAttrib3f(ValidationContext *context,
5351 GLuint index,
5352 GLfloat x,
5353 GLfloat y,
5354 GLfloat z)
5355{
5356 return ValidateVertexAttribIndex(context, index);
5357}
5358
5359bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5360{
5361 return ValidateVertexAttribIndex(context, index);
5362}
5363
5364bool ValidateVertexAttrib4f(ValidationContext *context,
5365 GLuint index,
5366 GLfloat x,
5367 GLfloat y,
5368 GLfloat z,
5369 GLfloat w)
5370{
5371 return ValidateVertexAttribIndex(context, index);
5372}
5373
5374bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5375{
5376 return ValidateVertexAttribIndex(context, index);
5377}
5378
5379bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5380{
5381 if (width < 0 || height < 0)
5382 {
5383 context->handleError(
5384 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
5385 return false;
5386 }
5387
5388 return true;
5389}
5390
5391bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5392{
5393 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5394}
5395
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005396bool ValidateDrawElements(ValidationContext *context,
5397 GLenum mode,
5398 GLsizei count,
5399 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005400 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005401{
5402 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5403}
5404
Jamie Madillbe849e42017-05-02 15:49:00 -04005405bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5406 GLenum target,
5407 GLenum attachment,
5408 GLenum pname,
5409 GLint *params)
5410{
5411 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5412 nullptr);
5413}
5414
5415bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5416{
5417 return ValidateGetProgramivBase(context, program, pname, nullptr);
5418}
5419
5420bool ValidateCopyTexImage2D(ValidationContext *context,
5421 GLenum target,
5422 GLint level,
5423 GLenum internalformat,
5424 GLint x,
5425 GLint y,
5426 GLsizei width,
5427 GLsizei height,
5428 GLint border)
5429{
5430 if (context->getClientMajorVersion() < 3)
5431 {
5432 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5433 0, x, y, width, height, border);
5434 }
5435
5436 ASSERT(context->getClientMajorVersion() == 3);
5437 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5438 0, x, y, width, height, border);
5439}
5440
5441bool ValidateCopyTexSubImage2D(Context *context,
5442 GLenum target,
5443 GLint level,
5444 GLint xoffset,
5445 GLint yoffset,
5446 GLint x,
5447 GLint y,
5448 GLsizei width,
5449 GLsizei height)
5450{
5451 if (context->getClientMajorVersion() < 3)
5452 {
5453 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5454 yoffset, x, y, width, height, 0);
5455 }
5456
5457 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5458 yoffset, 0, x, y, width, height, 0);
5459}
5460
5461bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5462{
5463 return ValidateGenOrDelete(context, n);
5464}
5465
5466bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5467{
5468 return ValidateGenOrDelete(context, n);
5469}
5470
5471bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5472{
5473 return ValidateGenOrDelete(context, n);
5474}
5475
5476bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5477{
5478 return ValidateGenOrDelete(context, n);
5479}
5480
5481bool ValidateDisable(Context *context, GLenum cap)
5482{
5483 if (!ValidCap(context, cap, false))
5484 {
5485 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5486 return false;
5487 }
5488
5489 return true;
5490}
5491
5492bool ValidateEnable(Context *context, GLenum cap)
5493{
5494 if (!ValidCap(context, cap, false))
5495 {
5496 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5497 return false;
5498 }
5499
5500 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5501 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5502 {
5503 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5504 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5505
5506 // We also output an error message to the debugger window if tracing is active, so that
5507 // developers can see the error message.
5508 ERR() << errorMessage;
5509 return false;
5510 }
5511
5512 return true;
5513}
5514
5515bool ValidateFramebufferRenderbuffer(Context *context,
5516 GLenum target,
5517 GLenum attachment,
5518 GLenum renderbuffertarget,
5519 GLuint renderbuffer)
5520{
5521 if (!ValidFramebufferTarget(target) ||
5522 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5523 {
5524 context->handleError(Error(GL_INVALID_ENUM));
5525 return false;
5526 }
5527
5528 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5529 renderbuffertarget, renderbuffer);
5530}
5531
5532bool ValidateFramebufferTexture2D(Context *context,
5533 GLenum target,
5534 GLenum attachment,
5535 GLenum textarget,
5536 GLuint texture,
5537 GLint level)
5538{
5539 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5540 // extension
5541 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5542 level != 0)
5543 {
5544 context->handleError(Error(GL_INVALID_VALUE));
5545 return false;
5546 }
5547
5548 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5549 {
5550 return false;
5551 }
5552
5553 if (texture != 0)
5554 {
5555 gl::Texture *tex = context->getTexture(texture);
5556 ASSERT(tex);
5557
5558 const gl::Caps &caps = context->getCaps();
5559
5560 switch (textarget)
5561 {
5562 case GL_TEXTURE_2D:
5563 {
5564 if (level > gl::log2(caps.max2DTextureSize))
5565 {
5566 context->handleError(Error(GL_INVALID_VALUE));
5567 return false;
5568 }
5569 if (tex->getTarget() != GL_TEXTURE_2D)
5570 {
5571 context->handleError(Error(GL_INVALID_OPERATION,
5572 "Textarget must match the texture target type."));
5573 return false;
5574 }
5575 }
5576 break;
5577
5578 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5579 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5580 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5581 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5582 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5583 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5584 {
5585 if (level > gl::log2(caps.maxCubeMapTextureSize))
5586 {
5587 context->handleError(Error(GL_INVALID_VALUE));
5588 return false;
5589 }
5590 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5591 {
5592 context->handleError(Error(GL_INVALID_OPERATION,
5593 "Textarget must match the texture target type."));
5594 return false;
5595 }
5596 }
5597 break;
5598
5599 case GL_TEXTURE_2D_MULTISAMPLE:
5600 {
5601 if (context->getClientVersion() < ES_3_1)
5602 {
5603 context->handleError(Error(GL_INVALID_OPERATION,
5604 "Texture target requires at least OpenGL ES 3.1."));
5605 return false;
5606 }
5607
5608 if (level != 0)
5609 {
5610 context->handleError(
5611 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
5612 return false;
5613 }
5614 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5615 {
5616 context->handleError(Error(GL_INVALID_OPERATION,
5617 "Textarget must match the texture target type."));
5618 return false;
5619 }
5620 }
5621 break;
5622
5623 default:
5624 context->handleError(Error(GL_INVALID_ENUM));
5625 return false;
5626 }
5627
5628 const Format &format = tex->getFormat(textarget, level);
5629 if (format.info->compressed)
5630 {
5631 context->handleError(Error(GL_INVALID_OPERATION));
5632 return false;
5633 }
5634 }
5635
5636 return true;
5637}
5638
5639bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5640{
5641 return ValidateGenOrDelete(context, n);
5642}
5643
5644bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5645{
5646 return ValidateGenOrDelete(context, n);
5647}
5648
5649bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5650{
5651 return ValidateGenOrDelete(context, n);
5652}
5653
5654bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5655{
5656 return ValidateGenOrDelete(context, n);
5657}
5658
5659bool ValidateGenerateMipmap(Context *context, GLenum target)
5660{
5661 if (!ValidTextureTarget(context, target))
5662 {
5663 context->handleError(Error(GL_INVALID_ENUM));
5664 return false;
5665 }
5666
5667 Texture *texture = context->getTargetTexture(target);
5668
5669 if (texture == nullptr)
5670 {
5671 context->handleError(Error(GL_INVALID_OPERATION));
5672 return false;
5673 }
5674
5675 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5676
5677 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5678 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5679 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5680 {
5681 context->handleError(Error(GL_INVALID_OPERATION));
5682 return false;
5683 }
5684
5685 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5686 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5687 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5688
5689 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5690 // unsized formats or that are color renderable and filterable. Since we do not track if
5691 // the texture was created with sized or unsized format (only sized formats are stored),
5692 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5693 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5694 // textures since they're the only texture format that can be created with unsized formats
5695 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5696 // was the last version to use add them.
5697 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5698 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5699 {
5700 context->handleError(Error(GL_INVALID_OPERATION));
5701 return false;
5702 }
5703
Geoff Lang65ac5b92017-05-01 13:16:30 -04005704 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5705 bool supportsSRGBMipmapGeneration =
5706 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5707 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 {
Geoff Lang65ac5b92017-05-01 13:16:30 -04005709 context->handleError(
5710 Error(GL_INVALID_OPERATION, "Mipmap generation of sRGB textures is not allowed."));
Jamie Madillbe849e42017-05-02 15:49:00 -04005711 return false;
5712 }
5713
5714 // Non-power of 2 ES2 check
5715 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5716 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5717 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5718 {
5719 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
5720 context->handleError(Error(GL_INVALID_OPERATION));
5721 return false;
5722 }
5723
5724 // Cube completeness check
5725 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5726 {
5727 context->handleError(Error(GL_INVALID_OPERATION));
5728 return false;
5729 }
5730
5731 return true;
5732}
5733
5734bool ValidateGetBufferParameteriv(ValidationContext *context,
5735 GLenum target,
5736 GLenum pname,
5737 GLint *params)
5738{
5739 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5740}
5741
5742bool ValidateGetRenderbufferParameteriv(Context *context,
5743 GLenum target,
5744 GLenum pname,
5745 GLint *params)
5746{
5747 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5748}
5749
5750bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5751{
5752 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5753}
5754
5755bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5756{
5757 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5758}
5759
5760bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5761{
5762 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5763}
5764
5765bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5766{
5767 return ValidateGetUniformBase(context, program, location);
5768}
5769
5770bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5771{
5772 return ValidateGetUniformBase(context, program, location);
5773}
5774
5775bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5776{
5777 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5778}
5779
5780bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5781{
5782 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5783}
5784
5785bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5786{
5787 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5788}
5789
5790bool ValidateIsEnabled(Context *context, GLenum cap)
5791{
5792 if (!ValidCap(context, cap, true))
5793 {
5794 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5795 return false;
5796 }
5797
5798 return true;
5799}
5800
5801bool ValidateLinkProgram(Context *context, GLuint program)
5802{
5803 if (context->hasActiveTransformFeedback(program))
5804 {
5805 // ES 3.0.4 section 2.15 page 91
5806 context->handleError(Error(GL_INVALID_OPERATION,
5807 "Cannot link program while program is associated with an active "
5808 "transform feedback object."));
5809 return false;
5810 }
5811
5812 Program *programObject = GetValidProgram(context, program);
5813 if (!programObject)
5814 {
5815 return false;
5816 }
5817
5818 return true;
5819}
5820
5821bool ValidateReadPixels(ValidationContext *context,
5822 GLint x,
5823 GLint y,
5824 GLsizei width,
5825 GLsizei height,
5826 GLenum format,
5827 GLenum type,
5828 void *pixels)
5829{
5830 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5831 nullptr, pixels);
5832}
5833
5834bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5835{
5836 return ValidateTexParameterBase(context, target, pname, -1, &param);
5837}
5838
5839bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5840{
5841 return ValidateTexParameterBase(context, target, pname, -1, params);
5842}
5843
5844bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5845{
5846 return ValidateTexParameterBase(context, target, pname, -1, &param);
5847}
5848
5849bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5850{
5851 return ValidateTexParameterBase(context, target, pname, -1, params);
5852}
5853
5854bool ValidateUseProgram(Context *context, GLuint program)
5855{
5856 if (program != 0)
5857 {
5858 Program *programObject = context->getProgram(program);
5859 if (!programObject)
5860 {
5861 // ES 3.1.0 section 7.3 page 72
5862 if (context->getShader(program))
5863 {
5864 context->handleError(
5865 Error(GL_INVALID_OPERATION,
5866 "Attempted to use a single shader instead of a shader program."));
5867 return false;
5868 }
5869 else
5870 {
5871 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
5872 return false;
5873 }
5874 }
5875 if (!programObject->isLinked())
5876 {
5877 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
5878 return false;
5879 }
5880 }
5881 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5882 {
5883 // ES 3.0.4 section 2.15 page 91
5884 context->handleError(
5885 Error(GL_INVALID_OPERATION,
5886 "Cannot change active program while transform feedback is unpaused."));
5887 return false;
5888 }
5889
5890 return true;
5891}
5892
Jamie Madillc29968b2016-01-20 11:17:23 -05005893} // namespace gl