1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // 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
9 #include "libANGLE/validationES2_autogen.h"
10
11 #include <cstdint>
12
13 #include "common/mathutil.h"
14 #include "common/string_utils.h"
15 #include "common/utilities.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/ErrorStrings.h"
18 #include "libANGLE/Fence.h"
19 #include "libANGLE/Framebuffer.h"
20 #include "libANGLE/FramebufferAttachment.h"
21 #include "libANGLE/MemoryObject.h"
22 #include "libANGLE/Renderbuffer.h"
23 #include "libANGLE/Shader.h"
24 #include "libANGLE/Texture.h"
25 #include "libANGLE/Uniform.h"
26 #include "libANGLE/VertexArray.h"
27 #include "libANGLE/formatutils.h"
28 #include "libANGLE/validationES.h"
29 #include "libANGLE/validationES2.h"
30 #include "libANGLE/validationES3_autogen.h"
31
32 namespace gl
33 {
34 using namespace err;
35
36 namespace
37 {
38
IsPartialBlit(const Context * context,const FramebufferAttachment * readBuffer,const FramebufferAttachment * writeBuffer,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1)39 bool IsPartialBlit(const Context *context,
40 const FramebufferAttachment *readBuffer,
41 const FramebufferAttachment *writeBuffer,
42 GLint srcX0,
43 GLint srcY0,
44 GLint srcX1,
45 GLint srcY1,
46 GLint dstX0,
47 GLint dstY0,
48 GLint dstX1,
49 GLint dstY1)
50 {
51 const Extents &writeSize = writeBuffer->getSize();
52 const Extents &readSize = readBuffer->getSize();
53
54 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
55 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
56 {
57 return true;
58 }
59
60 if (context->getState().isScissorTestEnabled())
61 {
62 const Rectangle &scissor = context->getState().getScissor();
63 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
64 scissor.height < writeSize.height;
65 }
66
67 return false;
68 }
69
IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)70 bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
71 {
72 // Table 1.1 from the CHROMIUM_copy_texture spec
73 switch (GetUnsizedFormat(internalFormat))
74 {
75 case GL_RED:
76 case GL_ALPHA:
77 case GL_LUMINANCE:
78 case GL_LUMINANCE_ALPHA:
79 case GL_RGB:
80 case GL_RGBA:
81 case GL_RGB8:
82 case GL_RGBA8:
83 case GL_BGRA_EXT:
84 case GL_BGRA8_EXT:
85 return true;
86
87 default:
88 return false;
89 }
90 }
91
IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)92 bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
93 {
94 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
95 }
96
IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)97 bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
98 {
99 // Table 1.0 from the CHROMIUM_copy_texture spec
100 switch (internalFormat)
101 {
102 case GL_RGB:
103 case GL_RGBA:
104 case GL_RGB8:
105 case GL_RGBA8:
106 case GL_BGRA_EXT:
107 case GL_BGRA8_EXT:
108 case GL_SRGB_EXT:
109 case GL_SRGB_ALPHA_EXT:
110 case GL_R8:
111 case GL_R8UI:
112 case GL_RG8:
113 case GL_RG8UI:
114 case GL_SRGB8:
115 case GL_RGB565:
116 case GL_RGB8UI:
117 case GL_RGB10_A2:
118 case GL_SRGB8_ALPHA8:
119 case GL_RGB5_A1:
120 case GL_RGBA4:
121 case GL_RGBA8UI:
122 case GL_RGB9_E5:
123 case GL_R16F:
124 case GL_R32F:
125 case GL_RG16F:
126 case GL_RG32F:
127 case GL_RGB16F:
128 case GL_RGB32F:
129 case GL_RGBA16F:
130 case GL_RGBA32F:
131 case GL_R11F_G11F_B10F:
132 case GL_LUMINANCE:
133 case GL_LUMINANCE_ALPHA:
134 case GL_ALPHA:
135 return true;
136
137 default:
138 return false;
139 }
140 }
141
IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)142 bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
143 {
144 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
145 }
146
IsValidCopyTextureDestinationFormatType(const Context * context,GLint internalFormat,GLenum type)147 bool IsValidCopyTextureDestinationFormatType(const Context *context,
148 GLint internalFormat,
149 GLenum type)
150 {
151 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
152 {
153 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
154 return false;
155 }
156
157 if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
158 {
159 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
160 return false;
161 }
162
163 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
164 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
165 {
166 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
167 return false;
168 }
169
170 return true;
171 }
172
IsValidCopyTextureDestinationTargetEnum(const Context * context,TextureTarget target)173 bool IsValidCopyTextureDestinationTargetEnum(const Context *context, TextureTarget target)
174 {
175 switch (target)
176 {
177 case TextureTarget::_2D:
178 case TextureTarget::CubeMapNegativeX:
179 case TextureTarget::CubeMapNegativeY:
180 case TextureTarget::CubeMapNegativeZ:
181 case TextureTarget::CubeMapPositiveX:
182 case TextureTarget::CubeMapPositiveY:
183 case TextureTarget::CubeMapPositiveZ:
184 return true;
185
186 case TextureTarget::Rectangle:
187 return context->getExtensions().textureRectangle;
188
189 default:
190 return false;
191 }
192 }
193
IsValidCopyTextureDestinationTarget(const Context * context,TextureType textureType,TextureTarget target)194 bool IsValidCopyTextureDestinationTarget(const Context *context,
195 TextureType textureType,
196 TextureTarget target)
197 {
198 return TextureTargetToType(target) == textureType;
199 }
200
IsValidCopyTextureSourceTarget(const Context * context,TextureType type)201 bool IsValidCopyTextureSourceTarget(const Context *context, TextureType type)
202 {
203 switch (type)
204 {
205 case TextureType::_2D:
206 return true;
207 case TextureType::Rectangle:
208 return context->getExtensions().textureRectangle;
209 case TextureType::External:
210 return context->getExtensions().eglImageExternalOES;
211 case TextureType::VideoImage:
212 return context->getExtensions().webglVideoTexture;
213 default:
214 return false;
215 }
216 }
217
IsValidCopyTextureSourceLevel(const Context * context,TextureType type,GLint level)218 bool IsValidCopyTextureSourceLevel(const Context *context, TextureType type, GLint level)
219 {
220 if (!ValidMipLevel(context, type, level))
221 {
222 return false;
223 }
224
225 if (level > 0 && context->getClientVersion() < ES_3_0)
226 {
227 return false;
228 }
229
230 return true;
231 }
232
IsValidCopyTextureDestinationLevel(const Context * context,TextureType type,GLint level,GLsizei width,GLsizei height,bool isSubImage)233 bool IsValidCopyTextureDestinationLevel(const Context *context,
234 TextureType type,
235 GLint level,
236 GLsizei width,
237 GLsizei height,
238 bool isSubImage)
239 {
240 if (!ValidMipLevel(context, type, level))
241 {
242 return false;
243 }
244
245 if (!ValidImageSizeParameters(context, type, level, width, height, 1, isSubImage))
246 {
247 return false;
248 }
249
250 const Caps &caps = context->getCaps();
251 switch (type)
252 {
253 case TextureType::_2D:
254 return width <= (caps.max2DTextureSize >> level) &&
255 height <= (caps.max2DTextureSize >> level);
256 case TextureType::Rectangle:
257 ASSERT(level == 0);
258 return width <= (caps.max2DTextureSize >> level) &&
259 height <= (caps.max2DTextureSize >> level);
260
261 case TextureType::CubeMap:
262 return width <= (caps.maxCubeMapTextureSize >> level) &&
263 height <= (caps.maxCubeMapTextureSize >> level);
264 default:
265 return true;
266 }
267 }
268
IsValidStencilFunc(GLenum func)269 bool IsValidStencilFunc(GLenum func)
270 {
271 switch (func)
272 {
273 case GL_NEVER:
274 case GL_ALWAYS:
275 case GL_LESS:
276 case GL_LEQUAL:
277 case GL_EQUAL:
278 case GL_GEQUAL:
279 case GL_GREATER:
280 case GL_NOTEQUAL:
281 return true;
282
283 default:
284 return false;
285 }
286 }
287
IsValidStencilFace(GLenum face)288 bool IsValidStencilFace(GLenum face)
289 {
290 switch (face)
291 {
292 case GL_FRONT:
293 case GL_BACK:
294 case GL_FRONT_AND_BACK:
295 return true;
296
297 default:
298 return false;
299 }
300 }
301
IsValidStencilOp(GLenum op)302 bool IsValidStencilOp(GLenum op)
303 {
304 switch (op)
305 {
306 case GL_ZERO:
307 case GL_KEEP:
308 case GL_REPLACE:
309 case GL_INCR:
310 case GL_DECR:
311 case GL_INVERT:
312 case GL_INCR_WRAP:
313 case GL_DECR_WRAP:
314 return true;
315
316 default:
317 return false;
318 }
319 }
320
ValidateES2CopyTexImageParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)321 bool ValidateES2CopyTexImageParameters(const Context *context,
322 TextureTarget target,
323 GLint level,
324 GLenum internalformat,
325 bool isSubImage,
326 GLint xoffset,
327 GLint yoffset,
328 GLint x,
329 GLint y,
330 GLsizei width,
331 GLsizei height,
332 GLint border)
333 {
334 if (!ValidTexture2DDestinationTarget(context, target))
335 {
336 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
337 return false;
338 }
339
340 TextureType texType = TextureTargetToType(target);
341 if (!ValidImageSizeParameters(context, texType, level, width, height, 1, isSubImage))
342 {
343 // Error is already handled.
344 return false;
345 }
346
347 Format textureFormat = Format::Invalid();
348 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
349 xoffset, yoffset, 0, x, y, width, height, border,
350 &textureFormat))
351 {
352 return false;
353 }
354
355 const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
356 GLenum colorbufferFormat =
357 framebuffer->getReadColorAttachment()->getFormat().info->sizedInternalFormat;
358 const auto &formatInfo = *textureFormat.info;
359
360 // [OpenGL ES 2.0.24] table 3.9
361 if (isSubImage)
362 {
363 switch (formatInfo.format)
364 {
365 case GL_ALPHA:
366 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
367 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
368 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
369 {
370 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
371 return false;
372 }
373 break;
374 case GL_LUMINANCE:
375 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
376 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
377 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
378 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
379 colorbufferFormat != GL_BGR5_A1_ANGLEX)
380 {
381 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
382 return false;
383 }
384 break;
385 case GL_RED_EXT:
386 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
387 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
388 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
389 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
390 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
391 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
392 colorbufferFormat != GL_BGR5_A1_ANGLEX)
393 {
394 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
395 return false;
396 }
397 break;
398 case GL_RG_EXT:
399 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
400 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
401 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
402 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
403 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
404 colorbufferFormat != GL_BGR5_A1_ANGLEX)
405 {
406 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
407 return false;
408 }
409 break;
410 case GL_RGB:
411 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
412 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
413 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
414 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
415 colorbufferFormat != GL_BGR5_A1_ANGLEX)
416 {
417 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
418 return false;
419 }
420 break;
421 case GL_LUMINANCE_ALPHA:
422 case GL_RGBA:
423 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
424 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
425 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
426 {
427 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
428 return false;
429 }
430 break;
431 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
432 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
433 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
434 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
435 case GL_ETC1_RGB8_OES:
436 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
437 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
438 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
439 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
440 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
441 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
442 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
443 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
444 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
445 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
446 return false;
447 case GL_DEPTH_COMPONENT:
448 case GL_DEPTH_STENCIL_OES:
449 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
450 return false;
451 default:
452 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
453 return false;
454 }
455
456 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloatOES)
457 {
458 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
459 return false;
460 }
461 }
462 else
463 {
464 switch (internalformat)
465 {
466 case GL_ALPHA:
467 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
468 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
469 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
470 {
471 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
472 return false;
473 }
474 break;
475 case GL_LUMINANCE:
476 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
477 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
478 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
479 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
480 colorbufferFormat != GL_BGR5_A1_ANGLEX)
481 {
482 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
483 return false;
484 }
485 break;
486 case GL_RED_EXT:
487 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
488 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
489 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
490 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
491 colorbufferFormat != GL_BGR5_A1_ANGLEX)
492 {
493 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
494 return false;
495 }
496 break;
497 case GL_RG_EXT:
498 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
499 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
500 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
501 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
502 {
503 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
504 return false;
505 }
506 break;
507 case GL_RGB:
508 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
509 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
510 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
511 colorbufferFormat != GL_BGR5_A1_ANGLEX)
512 {
513 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
514 return false;
515 }
516 break;
517 case GL_LUMINANCE_ALPHA:
518 case GL_RGBA:
519 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
520 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
521 colorbufferFormat != GL_BGR5_A1_ANGLEX)
522 {
523 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
524 return false;
525 }
526 break;
527 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
528 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
529 if (context->getExtensions().textureCompressionDXT1)
530 {
531 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
532 return false;
533 }
534 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
535 return false;
536 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
537 if (context->getExtensions().textureCompressionDXT3)
538 {
539 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
540 return false;
541 }
542 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
543 return false;
544 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
545 if (context->getExtensions().textureCompressionDXT5)
546 {
547 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
548 return false;
549 }
550 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
551 return false;
552 case GL_ETC1_RGB8_OES:
553 if (context->getExtensions().compressedETC1RGB8TextureOES)
554 {
555 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
556 return false;
557 }
558 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
559 return false;
560 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
561 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
562 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
563 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
564 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
565 if (context->getExtensions().lossyETCDecode)
566 {
567 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
568 return false;
569 }
570 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
571 return false;
572 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
573 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
574 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
575 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
576 if (context->getExtensions().compressedTexturePVRTC)
577 {
578 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
579 return false;
580 }
581 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
582 return false;
583 case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
584 case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
585 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
586 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
587 if (context->getExtensions().compressedTexturePVRTCsRGB)
588 {
589 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
590 return false;
591 }
592 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
593 return false;
594 case GL_DEPTH_COMPONENT:
595 case GL_DEPTH_COMPONENT16:
596 case GL_DEPTH_COMPONENT32_OES:
597 if (context->getExtensions().depthTextureAny())
598 {
599 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
600 return false;
601 }
602 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
603 return false;
604 case GL_DEPTH_STENCIL_OES:
605 case GL_DEPTH24_STENCIL8_OES:
606 if (context->getExtensions().depthTextureAny() ||
607 context->getExtensions().packedDepthStencilOES ||
608 context->getExtensions().depthTextureCubeMapOES)
609 {
610 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
611 return false;
612 }
613 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
614 return false;
615 default:
616 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
617 return false;
618 }
619 }
620
621 // If width or height is zero, it is a no-op. Return false without setting an error.
622 return (width > 0 && height > 0);
623 }
624
ValidCap(const Context * context,GLenum cap,bool queryOnly)625 bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
626 {
627 switch (cap)
628 {
629 // EXT_multisample_compatibility
630 case GL_MULTISAMPLE_EXT:
631 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
632 return context->getExtensions().multisampleCompatibility;
633
634 case GL_CULL_FACE:
635 case GL_POLYGON_OFFSET_FILL:
636 case GL_SAMPLE_ALPHA_TO_COVERAGE:
637 case GL_SAMPLE_COVERAGE:
638 case GL_SCISSOR_TEST:
639 case GL_STENCIL_TEST:
640 case GL_DEPTH_TEST:
641 case GL_BLEND:
642 case GL_DITHER:
643 return true;
644
645 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
646 case GL_RASTERIZER_DISCARD:
647 return (context->getClientMajorVersion() >= 3);
648
649 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
650 case GL_DEBUG_OUTPUT:
651 return context->getExtensions().debug;
652
653 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
654 return queryOnly && context->getExtensions().bindGeneratesResource;
655
656 case GL_CLIENT_ARRAYS_ANGLE:
657 return queryOnly && context->getExtensions().clientArrays;
658
659 case GL_FRAMEBUFFER_SRGB_EXT:
660 return context->getExtensions().sRGBWriteControl;
661
662 case GL_SAMPLE_MASK:
663 return context->getClientVersion() >= Version(3, 1);
664
665 case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
666 return queryOnly && context->getExtensions().robustResourceInitialization;
667
668 case GL_TEXTURE_RECTANGLE_ANGLE:
669 return context->getExtensions().webglCompatibility;
670 }
671
672 // GLES1 emulation: GLES1-specific caps after this point
673 if (context->getClientVersion().major != 1)
674 {
675 return false;
676 }
677
678 switch (cap)
679 {
680 case GL_ALPHA_TEST:
681 case GL_VERTEX_ARRAY:
682 case GL_NORMAL_ARRAY:
683 case GL_COLOR_ARRAY:
684 case GL_TEXTURE_COORD_ARRAY:
685 case GL_TEXTURE_2D:
686 case GL_LIGHTING:
687 case GL_LIGHT0:
688 case GL_LIGHT1:
689 case GL_LIGHT2:
690 case GL_LIGHT3:
691 case GL_LIGHT4:
692 case GL_LIGHT5:
693 case GL_LIGHT6:
694 case GL_LIGHT7:
695 case GL_NORMALIZE:
696 case GL_RESCALE_NORMAL:
697 case GL_COLOR_MATERIAL:
698 case GL_CLIP_PLANE0:
699 case GL_CLIP_PLANE1:
700 case GL_CLIP_PLANE2:
701 case GL_CLIP_PLANE3:
702 case GL_CLIP_PLANE4:
703 case GL_CLIP_PLANE5:
704 case GL_FOG:
705 case GL_POINT_SMOOTH:
706 case GL_LINE_SMOOTH:
707 case GL_COLOR_LOGIC_OP:
708 return context->getClientVersion() < Version(2, 0);
709 case GL_POINT_SIZE_ARRAY_OES:
710 return context->getClientVersion() < Version(2, 0) &&
711 context->getExtensions().pointSizeArrayOES;
712 case GL_TEXTURE_CUBE_MAP:
713 return context->getClientVersion() < Version(2, 0) &&
714 context->getExtensions().textureCubeMapOES;
715 case GL_POINT_SPRITE_OES:
716 return context->getClientVersion() < Version(2, 0) &&
717 context->getExtensions().pointSpriteOES;
718 default:
719 return false;
720 }
721 }
722
723 // Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
724 // 3.1.
IsValidESSLCharacter(unsigned char c)725 bool IsValidESSLCharacter(unsigned char c)
726 {
727 // Printing characters are valid except " $ ` @ \ ' DEL.
728 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
729 c != '\'')
730 {
731 return true;
732 }
733
734 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
735 if (c >= 9 && c <= 13)
736 {
737 return true;
738 }
739
740 return false;
741 }
742
IsValidESSLString(const char * str,size_t len)743 bool IsValidESSLString(const char *str, size_t len)
744 {
745 for (size_t i = 0; i < len; i++)
746 {
747 if (!IsValidESSLCharacter(str[i]))
748 {
749 return false;
750 }
751 }
752
753 return true;
754 }
755
IsValidESSLShaderSourceString(const char * str,size_t len,bool lineContinuationAllowed)756 bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
757 {
758 enum class ParseState
759 {
760 // Have not seen an ASCII non-whitespace character yet on
761 // this line. Possible that we might see a preprocessor
762 // directive.
763 BEGINING_OF_LINE,
764
765 // Have seen at least one ASCII non-whitespace character
766 // on this line.
767 MIDDLE_OF_LINE,
768
769 // Handling a preprocessor directive. Passes through all
770 // characters up to the end of the line. Disables comment
771 // processing.
772 IN_PREPROCESSOR_DIRECTIVE,
773
774 // Handling a single-line comment. The comment text is
775 // replaced with a single space.
776 IN_SINGLE_LINE_COMMENT,
777
778 // Handling a multi-line comment. Newlines are passed
779 // through to preserve line numbers.
780 IN_MULTI_LINE_COMMENT
781 };
782
783 ParseState state = ParseState::BEGINING_OF_LINE;
784 size_t pos = 0;
785
786 while (pos < len)
787 {
788 char c = str[pos];
789 char next = pos + 1 < len ? str[pos + 1] : 0;
790
791 // Check for newlines
792 if (c == '\n' || c == '\r')
793 {
794 if (state != ParseState::IN_MULTI_LINE_COMMENT)
795 {
796 state = ParseState::BEGINING_OF_LINE;
797 }
798
799 pos++;
800 continue;
801 }
802
803 switch (state)
804 {
805 case ParseState::BEGINING_OF_LINE:
806 if (c == ' ')
807 {
808 // Maintain the BEGINING_OF_LINE state until a non-space is seen
809 pos++;
810 }
811 else if (c == '#')
812 {
813 state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
814 pos++;
815 }
816 else
817 {
818 // Don't advance, re-process this character with the MIDDLE_OF_LINE state
819 state = ParseState::MIDDLE_OF_LINE;
820 }
821 break;
822
823 case ParseState::MIDDLE_OF_LINE:
824 if (c == '/' && next == '/')
825 {
826 state = ParseState::IN_SINGLE_LINE_COMMENT;
827 pos++;
828 }
829 else if (c == '/' && next == '*')
830 {
831 state = ParseState::IN_MULTI_LINE_COMMENT;
832 pos++;
833 }
834 else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
835 {
836 // Skip line continuation characters
837 }
838 else if (!IsValidESSLCharacter(c))
839 {
840 return false;
841 }
842 pos++;
843 break;
844
845 case ParseState::IN_PREPROCESSOR_DIRECTIVE:
846 // Line-continuation characters may not be permitted.
847 // Otherwise, just pass it through. Do not parse comments in this state.
848 if (!lineContinuationAllowed && c == '\\')
849 {
850 return false;
851 }
852 pos++;
853 break;
854
855 case ParseState::IN_SINGLE_LINE_COMMENT:
856 // Line-continuation characters are processed before comment processing.
857 // Advance string if a new line character is immediately behind
858 // line-continuation character.
859 if (c == '\\' && (next == '\n' || next == '\r'))
860 {
861 pos++;
862 }
863 pos++;
864 break;
865
866 case ParseState::IN_MULTI_LINE_COMMENT:
867 if (c == '*' && next == '/')
868 {
869 state = ParseState::MIDDLE_OF_LINE;
870 pos++;
871 }
872 pos++;
873 break;
874 }
875 }
876
877 return true;
878 }
879
ValidateWebGLNamePrefix(const Context * context,const GLchar * name)880 bool ValidateWebGLNamePrefix(const Context *context, const GLchar *name)
881 {
882 ASSERT(context->isWebGL());
883
884 // WebGL 1.0 [Section 6.16] GLSL Constructs
885 // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
886 if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
887 {
888 context->validationError(GL_INVALID_OPERATION, kWebglBindAttribLocationReservedPrefix);
889 return false;
890 }
891
892 return true;
893 }
894
ValidateWebGLNameLength(const Context * context,size_t length)895 bool ValidateWebGLNameLength(const Context *context, size_t length)
896 {
897 ASSERT(context->isWebGL());
898
899 if (context->isWebGL1() && length > 256)
900 {
901 // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
902 // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
903 // locations.
904 context->validationError(GL_INVALID_VALUE, kWebglNameLengthLimitExceeded);
905
906 return false;
907 }
908 else if (length > 1024)
909 {
910 // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
911 // uniform and attribute locations.
912 context->validationError(GL_INVALID_VALUE, kWebgl2NameLengthLimitExceeded);
913 return false;
914 }
915
916 return true;
917 }
918
ValidBlendFunc(const Context * context,GLenum val)919 bool ValidBlendFunc(const Context *context, GLenum val)
920 {
921 const Extensions &ext = context->getExtensions();
922
923 // these are always valid for src and dst.
924 switch (val)
925 {
926 case GL_ZERO:
927 case GL_ONE:
928 case GL_SRC_COLOR:
929 case GL_ONE_MINUS_SRC_COLOR:
930 case GL_DST_COLOR:
931 case GL_ONE_MINUS_DST_COLOR:
932 case GL_SRC_ALPHA:
933 case GL_ONE_MINUS_SRC_ALPHA:
934 case GL_DST_ALPHA:
935 case GL_ONE_MINUS_DST_ALPHA:
936 case GL_CONSTANT_COLOR:
937 case GL_ONE_MINUS_CONSTANT_COLOR:
938 case GL_CONSTANT_ALPHA:
939 case GL_ONE_MINUS_CONSTANT_ALPHA:
940 return true;
941
942 // EXT_blend_func_extended.
943 case GL_SRC1_COLOR_EXT:
944 case GL_SRC1_ALPHA_EXT:
945 case GL_ONE_MINUS_SRC1_COLOR_EXT:
946 case GL_ONE_MINUS_SRC1_ALPHA_EXT:
947 case GL_SRC_ALPHA_SATURATE_EXT:
948 return ext.blendFuncExtended;
949
950 default:
951 return false;
952 }
953 }
954
ValidSrcBlendFunc(const Context * context,GLenum val)955 bool ValidSrcBlendFunc(const Context *context, GLenum val)
956 {
957 if (ValidBlendFunc(context, val))
958 return true;
959
960 if (val == GL_SRC_ALPHA_SATURATE)
961 return true;
962
963 return false;
964 }
965
ValidDstBlendFunc(const Context * context,GLenum val)966 bool ValidDstBlendFunc(const Context *context, GLenum val)
967 {
968 if (ValidBlendFunc(context, val))
969 return true;
970
971 if (val == GL_SRC_ALPHA_SATURATE)
972 {
973 if (context->getClientMajorVersion() >= 3)
974 return true;
975 }
976
977 return false;
978 }
979
IsValidImageLayout(ImageLayout layout)980 bool IsValidImageLayout(ImageLayout layout)
981 {
982 switch (layout)
983 {
984 case ImageLayout::Undefined:
985 case ImageLayout::General:
986 case ImageLayout::ColorAttachment:
987 case ImageLayout::DepthStencilAttachment:
988 case ImageLayout::DepthStencilReadOnlyAttachment:
989 case ImageLayout::ShaderReadOnly:
990 case ImageLayout::TransferSrc:
991 case ImageLayout::TransferDst:
992 case ImageLayout::DepthReadOnlyStencilAttachment:
993 case ImageLayout::DepthAttachmentStencilReadOnly:
994 return true;
995
996 default:
997 return false;
998 }
999 }
1000
ValidateES2TexImageParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)1001 bool ValidateES2TexImageParameters(const Context *context,
1002 TextureTarget target,
1003 GLint level,
1004 GLenum internalformat,
1005 bool isCompressed,
1006 bool isSubImage,
1007 GLint xoffset,
1008 GLint yoffset,
1009 GLsizei width,
1010 GLsizei height,
1011 GLint border,
1012 GLenum format,
1013 GLenum type,
1014 GLsizei imageSize,
1015 const void *pixels)
1016 {
1017 if (!ValidTexture2DDestinationTarget(context, target))
1018 {
1019 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1020 return false;
1021 }
1022
1023 return ValidateES2TexImageParametersBase(context, target, level, internalformat, isCompressed,
1024 isSubImage, xoffset, yoffset, width, height, border,
1025 format, type, imageSize, pixels);
1026 }
1027
IsValidMemoryObjectParamater(const Context * context,GLenum pname)1028 bool IsValidMemoryObjectParamater(const Context *context, GLenum pname)
1029 {
1030 switch (pname)
1031 {
1032 case GL_DEDICATED_MEMORY_OBJECT_EXT:
1033 return true;
1034
1035 default:
1036 return false;
1037 }
1038 }
1039
1040 } // anonymous namespace
1041
ValidateES2TexImageParametersBase(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)1042 bool ValidateES2TexImageParametersBase(const Context *context,
1043 TextureTarget target,
1044 GLint level,
1045 GLenum internalformat,
1046 bool isCompressed,
1047 bool isSubImage,
1048 GLint xoffset,
1049 GLint yoffset,
1050 GLsizei width,
1051 GLsizei height,
1052 GLint border,
1053 GLenum format,
1054 GLenum type,
1055 GLsizei imageSize,
1056 const void *pixels)
1057 {
1058
1059 TextureType texType = TextureTargetToType(target);
1060 if (!ValidImageSizeParameters(context, texType, level, width, height, 1, isSubImage))
1061 {
1062 // Error already handled.
1063 return false;
1064 }
1065
1066 if (!ValidMipLevel(context, texType, level))
1067 {
1068 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
1069 return false;
1070 }
1071
1072 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
1073 std::numeric_limits<GLsizei>::max() - yoffset < height)
1074 {
1075 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1076 return false;
1077 }
1078
1079 const Caps &caps = context->getCaps();
1080
1081 switch (texType)
1082 {
1083 case TextureType::_2D:
1084 case TextureType::External:
1085 case TextureType::VideoImage:
1086 if (width > (caps.max2DTextureSize >> level) ||
1087 height > (caps.max2DTextureSize >> level))
1088 {
1089 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1090 return false;
1091 }
1092 break;
1093
1094 case TextureType::Rectangle:
1095 ASSERT(level == 0);
1096 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
1097 {
1098 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1099 return false;
1100 }
1101 if (isCompressed)
1102 {
1103 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
1104 return false;
1105 }
1106 break;
1107
1108 case TextureType::CubeMap:
1109 if (!isSubImage && width != height)
1110 {
1111 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1112 return false;
1113 }
1114
1115 if (width > (caps.maxCubeMapTextureSize >> level) ||
1116 height > (caps.maxCubeMapTextureSize >> level))
1117 {
1118 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1119 return false;
1120 }
1121 break;
1122
1123 default:
1124 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1125 return false;
1126 }
1127
1128 Texture *texture = context->getTextureByType(texType);
1129 if (!texture)
1130 {
1131 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
1132 return false;
1133 }
1134
1135 // Verify zero border
1136 if (border != 0)
1137 {
1138 context->validationError(GL_INVALID_VALUE, kInvalidBorder);
1139 return false;
1140 }
1141
1142 bool nonEqualFormatsAllowed = false;
1143
1144 if (isCompressed)
1145 {
1146 GLenum actualInternalFormat =
1147 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1148 : internalformat;
1149
1150 const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(actualInternalFormat);
1151
1152 if (!internalFormatInfo.compressed)
1153 {
1154 context->validationError(GL_INVALID_ENUM, kInvalidInternalFormat);
1155 return false;
1156 }
1157
1158 if (!internalFormatInfo.textureSupport(context->getClientVersion(),
1159 context->getExtensions()))
1160 {
1161 context->validationError(GL_INVALID_ENUM, kInvalidInternalFormat);
1162 return false;
1163 }
1164
1165 if (isSubImage)
1166 {
1167 // From the OES_compressed_ETC1_RGB8_texture spec:
1168 //
1169 // INVALID_OPERATION is generated by CompressedTexSubImage2D, TexSubImage2D, or
1170 // CopyTexSubImage2D if the texture image <level> bound to <target> has internal format
1171 // ETC1_RGB8_OES.
1172 //
1173 // This is relaxed if GL_EXT_compressed_ETC1_RGB8_sub_texture is supported.
1174 if (actualInternalFormat == GL_ETC1_RGB8_OES &&
1175 !context->getExtensions().compressedETC1RGB8SubTexture)
1176 {
1177 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
1178 return false;
1179 }
1180
1181 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, 0,
1182 width, height, 1, texture->getWidth(target, level),
1183 texture->getHeight(target, level),
1184 texture->getDepth(target, level)))
1185 {
1186 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1187 return false;
1188 }
1189
1190 if (format != actualInternalFormat)
1191 {
1192 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1193 return false;
1194 }
1195 }
1196 else
1197 {
1198 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height, 1))
1199 {
1200 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1201 return false;
1202 }
1203 }
1204 }
1205 else
1206 {
1207 // validate <type> by itself (used as secondary key below)
1208 switch (type)
1209 {
1210 case GL_UNSIGNED_BYTE:
1211 case GL_UNSIGNED_SHORT_5_6_5:
1212 case GL_UNSIGNED_SHORT_4_4_4_4:
1213 case GL_UNSIGNED_SHORT_5_5_5_1:
1214 case GL_UNSIGNED_SHORT:
1215 case GL_UNSIGNED_INT:
1216 case GL_UNSIGNED_INT_24_8_OES:
1217 case GL_HALF_FLOAT_OES:
1218 case GL_FLOAT:
1219 break;
1220 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1221 if (!context->getExtensions().textureFormat2101010REV)
1222 {
1223 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1224 return false;
1225 }
1226 break;
1227 default:
1228 context->validationError(GL_INVALID_ENUM, kInvalidType);
1229 return false;
1230 }
1231
1232 // validate <format> + <type> combinations
1233 // - invalid <format> -> sets INVALID_ENUM
1234 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1235 switch (format)
1236 {
1237 case GL_ALPHA:
1238 case GL_LUMINANCE:
1239 case GL_LUMINANCE_ALPHA:
1240 switch (type)
1241 {
1242 case GL_UNSIGNED_BYTE:
1243 case GL_FLOAT:
1244 case GL_HALF_FLOAT_OES:
1245 break;
1246 default:
1247 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1248 return false;
1249 }
1250 break;
1251 case GL_RED:
1252 case GL_RG:
1253 if (!context->getExtensions().textureRG)
1254 {
1255 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1256 return false;
1257 }
1258 switch (type)
1259 {
1260 case GL_UNSIGNED_BYTE:
1261 break;
1262 case GL_FLOAT:
1263 case GL_HALF_FLOAT_OES:
1264 if (!context->getExtensions().textureFloatOES)
1265 {
1266 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1267 return false;
1268 }
1269 break;
1270 case GL_SHORT:
1271 case GL_UNSIGNED_SHORT:
1272 if (!context->getExtensions().textureNorm16)
1273 {
1274 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1275 return false;
1276 }
1277 break;
1278 default:
1279 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1280 return false;
1281 }
1282 break;
1283 case GL_RGB:
1284 switch (type)
1285 {
1286 case GL_UNSIGNED_BYTE:
1287 case GL_UNSIGNED_SHORT_5_6_5:
1288 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1289 case GL_FLOAT:
1290 case GL_HALF_FLOAT_OES:
1291 break;
1292 case GL_SHORT:
1293 case GL_UNSIGNED_SHORT:
1294 if (!context->getExtensions().textureNorm16)
1295 {
1296 context->validationError(GL_INVALID_OPERATION,
1297 kMismatchedTypeAndFormat);
1298 return false;
1299 }
1300 break;
1301 default:
1302 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1303 return false;
1304 }
1305 break;
1306 case GL_RGBA:
1307 switch (type)
1308 {
1309 case GL_UNSIGNED_BYTE:
1310 case GL_UNSIGNED_SHORT_4_4_4_4:
1311 case GL_UNSIGNED_SHORT_5_5_5_1:
1312 case GL_FLOAT:
1313 case GL_HALF_FLOAT_OES:
1314 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1315 break;
1316 case GL_SHORT:
1317 case GL_UNSIGNED_SHORT:
1318 if (!context->getExtensions().textureNorm16)
1319 {
1320 context->validationError(GL_INVALID_OPERATION,
1321 kMismatchedTypeAndFormat);
1322 return false;
1323 }
1324 break;
1325 default:
1326 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1327 return false;
1328 }
1329 break;
1330 case GL_BGRA_EXT:
1331 if (!context->getExtensions().textureFormatBGRA8888)
1332 {
1333 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1334 return false;
1335 }
1336 switch (type)
1337 {
1338 case GL_UNSIGNED_BYTE:
1339 break;
1340 default:
1341 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1342 return false;
1343 }
1344 break;
1345 case GL_SRGB_EXT:
1346 case GL_SRGB_ALPHA_EXT:
1347 if (!context->getExtensions().sRGB)
1348 {
1349 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1350 return false;
1351 }
1352 switch (type)
1353 {
1354 case GL_UNSIGNED_BYTE:
1355 break;
1356 default:
1357 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1358 return false;
1359 }
1360 break;
1361 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1362 // handled below
1363 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1364 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1365 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1366 break;
1367 case GL_DEPTH_COMPONENT:
1368 switch (type)
1369 {
1370 case GL_UNSIGNED_SHORT:
1371 case GL_UNSIGNED_INT:
1372 break;
1373 case GL_FLOAT:
1374 if (!context->getExtensions().depthBufferFloat2NV)
1375 {
1376 context->validationError(GL_INVALID_OPERATION,
1377 kMismatchedTypeAndFormat);
1378 return false;
1379 }
1380 break;
1381 default:
1382 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1383 return false;
1384 }
1385 break;
1386 case GL_DEPTH_STENCIL_OES:
1387 switch (type)
1388 {
1389 case GL_UNSIGNED_INT_24_8_OES:
1390 break;
1391 default:
1392 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1393 return false;
1394 }
1395 break;
1396 default:
1397 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1398 return false;
1399 }
1400
1401 switch (format)
1402 {
1403 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1404 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1405 if (context->getExtensions().textureCompressionDXT1)
1406 {
1407 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1408 return false;
1409 }
1410 else
1411 {
1412 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1413 return false;
1414 }
1415 break;
1416 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1417 if (context->getExtensions().textureCompressionDXT3)
1418 {
1419 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1420 return false;
1421 }
1422 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1423 return false;
1424 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1425 if (context->getExtensions().textureCompressionDXT5)
1426 {
1427 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1428 return false;
1429 }
1430 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1431 return false;
1432 case GL_ETC1_RGB8_OES:
1433 if (context->getExtensions().compressedETC1RGB8TextureOES)
1434 {
1435 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1436 return false;
1437 }
1438 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1439 return false;
1440 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1441 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1442 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1443 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1444 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1445 if (context->getExtensions().lossyETCDecode)
1446 {
1447 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1448 return false;
1449 }
1450 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1451 return false;
1452 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
1453 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
1454 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
1455 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
1456 if (context->getExtensions().compressedTexturePVRTC)
1457 {
1458 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1459 return false;
1460 }
1461 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1462 return false;
1463 case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
1464 case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
1465 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
1466 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
1467 if (context->getExtensions().compressedTexturePVRTCsRGB)
1468 {
1469 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1470 return false;
1471 }
1472 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1473 return false;
1474 case GL_DEPTH_COMPONENT:
1475 case GL_DEPTH_STENCIL_OES:
1476 if (!context->getExtensions().depthTextureANGLE &&
1477 !((context->getExtensions().packedDepthStencilOES ||
1478 context->getExtensions().depthTextureCubeMapOES) &&
1479 context->getExtensions().depthTextureOES))
1480 {
1481 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1482 return false;
1483 }
1484
1485 switch (target)
1486 {
1487 case TextureTarget::_2D:
1488 break;
1489 case TextureTarget::CubeMapNegativeX:
1490 case TextureTarget::CubeMapNegativeY:
1491 case TextureTarget::CubeMapNegativeZ:
1492 case TextureTarget::CubeMapPositiveX:
1493 case TextureTarget::CubeMapPositiveY:
1494 case TextureTarget::CubeMapPositiveZ:
1495 if (!context->getExtensions().depthTextureCubeMapOES)
1496 {
1497 context->validationError(GL_INVALID_OPERATION,
1498 kMismatchedTargetAndFormat);
1499 return false;
1500 }
1501 break;
1502 default:
1503 context->validationError(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
1504 return false;
1505 }
1506
1507 // OES_depth_texture supports loading depth data and multiple levels,
1508 // but ANGLE_depth_texture does not
1509 if (!context->getExtensions().depthTextureOES)
1510 {
1511 if (pixels != nullptr)
1512 {
1513 context->validationError(GL_INVALID_OPERATION, kPixelDataNotNull);
1514 return false;
1515 }
1516 if (level != 0)
1517 {
1518 context->validationError(GL_INVALID_OPERATION, kLevelNotZero);
1519 return false;
1520 }
1521 }
1522 break;
1523 default:
1524 break;
1525 }
1526
1527 if (!isSubImage)
1528 {
1529 switch (internalformat)
1530 {
1531 // Core ES 2.0 formats
1532 case GL_ALPHA:
1533 case GL_LUMINANCE:
1534 case GL_LUMINANCE_ALPHA:
1535 case GL_RGB:
1536 case GL_RGBA:
1537 break;
1538
1539 case GL_RGBA32F:
1540 if (!context->getExtensions().colorBufferFloatRGBA)
1541 {
1542 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1543 return false;
1544 }
1545
1546 nonEqualFormatsAllowed = true;
1547
1548 if (type != GL_FLOAT)
1549 {
1550 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1551 return false;
1552 }
1553 if (format != GL_RGBA)
1554 {
1555 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1556 return false;
1557 }
1558 break;
1559
1560 case GL_RGB32F:
1561 if (!context->getExtensions().colorBufferFloatRGB)
1562 {
1563 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1564 return false;
1565 }
1566
1567 nonEqualFormatsAllowed = true;
1568
1569 if (type != GL_FLOAT)
1570 {
1571 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1572 return false;
1573 }
1574 if (format != GL_RGB)
1575 {
1576 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1577 return false;
1578 }
1579 break;
1580
1581 case GL_BGRA_EXT:
1582 if (!context->getExtensions().textureFormatBGRA8888)
1583 {
1584 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1585 return false;
1586 }
1587 break;
1588
1589 case GL_DEPTH_COMPONENT:
1590 if (!(context->getExtensions().depthTextureAny()))
1591 {
1592 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1593 return false;
1594 }
1595 break;
1596
1597 case GL_DEPTH_STENCIL:
1598 if (!(context->getExtensions().depthTextureANGLE ||
1599 context->getExtensions().packedDepthStencilOES ||
1600 context->getExtensions().depthTextureCubeMapOES))
1601 {
1602 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1603 return false;
1604 }
1605 break;
1606
1607 case GL_RED:
1608 case GL_RG:
1609 if (!context->getExtensions().textureRG)
1610 {
1611 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1612 return false;
1613 }
1614 break;
1615
1616 case GL_SRGB_EXT:
1617 case GL_SRGB_ALPHA_EXT:
1618 if (!context->getExtensions().sRGB)
1619 {
1620 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1621 return false;
1622 }
1623 break;
1624
1625 case GL_RGB10_A2_EXT:
1626 if (!context->getExtensions().textureFormat2101010REV)
1627 {
1628 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1629 return false;
1630 }
1631
1632 if (type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT || format != GL_RGBA)
1633 {
1634 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1635 return false;
1636 }
1637
1638 nonEqualFormatsAllowed = true;
1639
1640 break;
1641
1642 case GL_RGB5_A1:
1643 if (context->getExtensions().textureFormat2101010REV &&
1644 type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGBA)
1645 {
1646 nonEqualFormatsAllowed = true;
1647 }
1648
1649 break;
1650
1651 case GL_R16_EXT:
1652 case GL_RG16_EXT:
1653 case GL_RGB16_EXT:
1654 case GL_RGBA16_EXT:
1655 case GL_R16_SNORM_EXT:
1656 case GL_RG16_SNORM_EXT:
1657 case GL_RGB16_SNORM_EXT:
1658 case GL_RGBA16_SNORM_EXT:
1659 if (!context->getExtensions().textureNorm16)
1660 {
1661 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1662 return false;
1663 }
1664 break;
1665 default:
1666 context->validationError(GL_INVALID_VALUE, kInvalidInternalFormat);
1667 return false;
1668 }
1669 }
1670
1671 if (type == GL_FLOAT)
1672 {
1673 if (!context->getExtensions().textureFloatOES)
1674 {
1675 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1676 return false;
1677 }
1678 }
1679 else if (type == GL_HALF_FLOAT_OES)
1680 {
1681 if (!context->getExtensions().textureHalfFloat)
1682 {
1683 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1684 return false;
1685 }
1686 }
1687 }
1688
1689 if (isSubImage)
1690 {
1691 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1692 if (textureInternalFormat.internalFormat == GL_NONE)
1693 {
1694 context->validationError(GL_INVALID_OPERATION, kInvalidTextureLevel);
1695 return false;
1696 }
1697
1698 if (format != textureInternalFormat.format)
1699 {
1700 context->validationError(GL_INVALID_OPERATION, err::kTextureFormatMismatch);
1701 return false;
1702 }
1703
1704 if (context->getExtensions().webglCompatibility)
1705 {
1706 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1707 textureInternalFormat.sizedInternalFormat)
1708 {
1709 context->validationError(GL_INVALID_OPERATION, kTextureTypeMismatch);
1710 return false;
1711 }
1712 }
1713
1714 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1715 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1716 {
1717 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
1718 return false;
1719 }
1720
1721 if (width > 0 && height > 0 && pixels == nullptr &&
1722 context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
1723 {
1724 context->validationError(GL_INVALID_VALUE, kPixelDataNull);
1725 return false;
1726 }
1727 }
1728 else
1729 {
1730 if (texture->getImmutableFormat())
1731 {
1732 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
1733 return false;
1734 }
1735 }
1736
1737 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
1738 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
1739 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
1740 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
1741 // case.
1742 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
1743 {
1744 context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
1745 return false;
1746 }
1747
1748 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1749 return ValidImageDataSize(context, texType, width, height, 1, sizeCheckFormat, type, pixels,
1750 imageSize);
1751 }
1752
ValidateES2TexStorageParameters(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)1753 bool ValidateES2TexStorageParameters(const Context *context,
1754 TextureType target,
1755 GLsizei levels,
1756 GLenum internalformat,
1757 GLsizei width,
1758 GLsizei height)
1759 {
1760 if (target != TextureType::_2D && target != TextureType::CubeMap &&
1761 target != TextureType::Rectangle)
1762 {
1763 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1764 return false;
1765 }
1766
1767 if (width < 1 || height < 1 || levels < 1)
1768 {
1769 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
1770 return false;
1771 }
1772
1773 if (target == TextureType::CubeMap && width != height)
1774 {
1775 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1776 return false;
1777 }
1778
1779 if (levels != 1 && levels != log2(std::max(width, height)) + 1)
1780 {
1781 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1782 return false;
1783 }
1784
1785 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1786 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
1787 {
1788 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1789 return false;
1790 }
1791
1792 const Caps &caps = context->getCaps();
1793
1794 switch (target)
1795 {
1796 case TextureType::_2D:
1797 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
1798 {
1799 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1800 return false;
1801 }
1802 break;
1803 case TextureType::Rectangle:
1804 if (levels != 1)
1805 {
1806 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
1807 return false;
1808 }
1809
1810 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
1811 {
1812 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1813 return false;
1814 }
1815 if (formatInfo.compressed)
1816 {
1817 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
1818 return false;
1819 }
1820 break;
1821 case TextureType::CubeMap:
1822 if (width > caps.maxCubeMapTextureSize || height > caps.maxCubeMapTextureSize)
1823 {
1824 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1825 return false;
1826 }
1827 break;
1828 default:
1829 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1830 return false;
1831 }
1832
1833 if (levels != 1 && !context->getExtensions().textureNPOTOES)
1834 {
1835 if (!isPow2(width) || !isPow2(height))
1836 {
1837 context->validationError(GL_INVALID_OPERATION, kDimensionsMustBePow2);
1838 return false;
1839 }
1840 }
1841
1842 switch (internalformat)
1843 {
1844 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1845 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1846 if (!context->getExtensions().textureCompressionDXT1)
1847 {
1848 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1849 return false;
1850 }
1851 break;
1852 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1853 if (!context->getExtensions().textureCompressionDXT3)
1854 {
1855 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1856 return false;
1857 }
1858 break;
1859 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1860 if (!context->getExtensions().textureCompressionDXT5)
1861 {
1862 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1863 return false;
1864 }
1865 break;
1866 case GL_ETC1_RGB8_OES:
1867 if (!context->getExtensions().compressedETC1RGB8TextureOES)
1868 {
1869 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1870 return false;
1871 }
1872 break;
1873 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1874 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1875 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1876 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1877 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1878 if (!context->getExtensions().lossyETCDecode)
1879 {
1880 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1881 return false;
1882 }
1883 break;
1884 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
1885 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
1886 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
1887 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
1888 if (!context->getExtensions().compressedTexturePVRTC)
1889 {
1890 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1891 return false;
1892 }
1893 break;
1894 case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
1895 case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
1896 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
1897 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
1898 if (!context->getExtensions().compressedTexturePVRTCsRGB)
1899 {
1900 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1901 return false;
1902 }
1903 break;
1904 case GL_RGBA32F_EXT:
1905 case GL_RGB32F_EXT:
1906 case GL_ALPHA32F_EXT:
1907 case GL_LUMINANCE32F_EXT:
1908 case GL_LUMINANCE_ALPHA32F_EXT:
1909 if (!context->getExtensions().textureFloatOES)
1910 {
1911 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1912 return false;
1913 }
1914 break;
1915 case GL_RGBA16F_EXT:
1916 case GL_RGB16F_EXT:
1917 case GL_ALPHA16F_EXT:
1918 case GL_LUMINANCE16F_EXT:
1919 case GL_LUMINANCE_ALPHA16F_EXT:
1920 if (!context->getExtensions().textureHalfFloat)
1921 {
1922 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1923 return false;
1924 }
1925 break;
1926 case GL_R8_EXT:
1927 case GL_RG8_EXT:
1928 if (!context->getExtensions().textureRG)
1929 {
1930 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1931 return false;
1932 }
1933 break;
1934 case GL_R16F_EXT:
1935 case GL_RG16F_EXT:
1936 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1937 {
1938 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1939 return false;
1940 }
1941 break;
1942 case GL_R32F_EXT:
1943 case GL_RG32F_EXT:
1944 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloatOES)
1945 {
1946 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1947 return false;
1948 }
1949 break;
1950 case GL_DEPTH_COMPONENT16:
1951 case GL_DEPTH_COMPONENT32_OES:
1952 if (!(context->getExtensions().depthTextureAny()))
1953 {
1954 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1955 return false;
1956 }
1957
1958 switch (target)
1959 {
1960 case TextureType::_2D:
1961 break;
1962 case TextureType::CubeMap:
1963 if (!context->getExtensions().depthTextureCubeMapOES)
1964 {
1965 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1966 return false;
1967 }
1968 break;
1969 default:
1970 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1971 return false;
1972 }
1973
1974 // ANGLE_depth_texture only supports 1-level textures
1975 if (!context->getExtensions().depthTextureOES)
1976 {
1977 if (levels != 1)
1978 {
1979 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1980 return false;
1981 }
1982 }
1983 break;
1984 case GL_DEPTH24_STENCIL8_OES:
1985 if (!(context->getExtensions().depthTextureANGLE ||
1986 ((context->getExtensions().packedDepthStencilOES ||
1987 context->getExtensions().depthTextureCubeMapOES) &&
1988 context->getExtensions().textureStorage)))
1989 {
1990 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1991 return false;
1992 }
1993
1994 switch (target)
1995 {
1996 case TextureType::_2D:
1997 break;
1998 case TextureType::CubeMap:
1999 if (!context->getExtensions().depthTextureCubeMapOES)
2000 {
2001 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
2002 return false;
2003 }
2004 break;
2005 default:
2006 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
2007 return false;
2008 }
2009
2010 if (!context->getExtensions().packedDepthStencilOES &&
2011 !context->getExtensions().depthTextureCubeMapOES)
2012 {
2013 // ANGLE_depth_texture only supports 1-level textures
2014 if (levels != 1)
2015 {
2016 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
2017 return false;
2018 }
2019 }
2020 break;
2021
2022 default:
2023 break;
2024 }
2025
2026 Texture *texture = context->getTextureByType(target);
2027 if (!texture || texture->id().value == 0)
2028 {
2029 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
2030 return false;
2031 }
2032
2033 if (texture->getImmutableFormat())
2034 {
2035 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
2036 return false;
2037 }
2038
2039 return true;
2040 }
2041
ValidateDiscardFramebufferEXT(const Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments)2042 bool ValidateDiscardFramebufferEXT(const Context *context,
2043 GLenum target,
2044 GLsizei numAttachments,
2045 const GLenum *attachments)
2046 {
2047 if (!context->getExtensions().discardFramebuffer)
2048 {
2049 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2050 return false;
2051 }
2052
2053 bool defaultFramebuffer = false;
2054
2055 switch (target)
2056 {
2057 case GL_FRAMEBUFFER:
2058 defaultFramebuffer =
2059 (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->isDefault());
2060 break;
2061 default:
2062 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
2063 return false;
2064 }
2065
2066 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
2067 defaultFramebuffer);
2068 }
2069
ValidateBindVertexArrayOES(const Context * context,VertexArrayID array)2070 bool ValidateBindVertexArrayOES(const Context *context, VertexArrayID array)
2071 {
2072 if (!context->getExtensions().vertexArrayObjectOES)
2073 {
2074 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2075 return false;
2076 }
2077
2078 return ValidateBindVertexArrayBase(context, array);
2079 }
2080
ValidateDeleteVertexArraysOES(const Context * context,GLsizei n,const VertexArrayID * arrays)2081 bool ValidateDeleteVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays)
2082 {
2083 if (!context->getExtensions().vertexArrayObjectOES)
2084 {
2085 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2086 return false;
2087 }
2088
2089 return ValidateGenOrDelete(context, n);
2090 }
2091
ValidateGenVertexArraysOES(const Context * context,GLsizei n,const VertexArrayID * arrays)2092 bool ValidateGenVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays)
2093 {
2094 if (!context->getExtensions().vertexArrayObjectOES)
2095 {
2096 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2097 return false;
2098 }
2099
2100 return ValidateGenOrDelete(context, n);
2101 }
2102
ValidateIsVertexArrayOES(const Context * context,VertexArrayID array)2103 bool ValidateIsVertexArrayOES(const Context *context, VertexArrayID array)
2104 {
2105 if (!context->getExtensions().vertexArrayObjectOES)
2106 {
2107 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2108 return false;
2109 }
2110
2111 return true;
2112 }
2113
ValidateProgramBinaryOES(const Context * context,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)2114 bool ValidateProgramBinaryOES(const Context *context,
2115 ShaderProgramID program,
2116 GLenum binaryFormat,
2117 const void *binary,
2118 GLint length)
2119 {
2120 if (!context->getExtensions().getProgramBinaryOES)
2121 {
2122 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2123 return false;
2124 }
2125
2126 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
2127 }
2128
ValidateGetProgramBinaryOES(const Context * context,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)2129 bool ValidateGetProgramBinaryOES(const Context *context,
2130 ShaderProgramID program,
2131 GLsizei bufSize,
2132 const GLsizei *length,
2133 const GLenum *binaryFormat,
2134 const void *binary)
2135 {
2136 if (!context->getExtensions().getProgramBinaryOES)
2137 {
2138 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2139 return false;
2140 }
2141
2142 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
2143 }
2144
ValidDebugSource(GLenum source,bool mustBeThirdPartyOrApplication)2145 static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
2146 {
2147 switch (source)
2148 {
2149 case GL_DEBUG_SOURCE_API:
2150 case GL_DEBUG_SOURCE_SHADER_COMPILER:
2151 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
2152 case GL_DEBUG_SOURCE_OTHER:
2153 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
2154 return !mustBeThirdPartyOrApplication;
2155
2156 case GL_DEBUG_SOURCE_THIRD_PARTY:
2157 case GL_DEBUG_SOURCE_APPLICATION:
2158 return true;
2159
2160 default:
2161 return false;
2162 }
2163 }
2164
ValidDebugType(GLenum type)2165 static bool ValidDebugType(GLenum type)
2166 {
2167 switch (type)
2168 {
2169 case GL_DEBUG_TYPE_ERROR:
2170 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
2171 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
2172 case GL_DEBUG_TYPE_PERFORMANCE:
2173 case GL_DEBUG_TYPE_PORTABILITY:
2174 case GL_DEBUG_TYPE_OTHER:
2175 case GL_DEBUG_TYPE_MARKER:
2176 case GL_DEBUG_TYPE_PUSH_GROUP:
2177 case GL_DEBUG_TYPE_POP_GROUP:
2178 return true;
2179
2180 default:
2181 return false;
2182 }
2183 }
2184
ValidDebugSeverity(GLenum severity)2185 static bool ValidDebugSeverity(GLenum severity)
2186 {
2187 switch (severity)
2188 {
2189 case GL_DEBUG_SEVERITY_HIGH:
2190 case GL_DEBUG_SEVERITY_MEDIUM:
2191 case GL_DEBUG_SEVERITY_LOW:
2192 case GL_DEBUG_SEVERITY_NOTIFICATION:
2193 return true;
2194
2195 default:
2196 return false;
2197 }
2198 }
2199
ValidateDebugMessageControlKHR(const Context * context,GLenum source,GLenum type,GLenum severity,GLsizei count,const GLuint * ids,GLboolean enabled)2200 bool ValidateDebugMessageControlKHR(const Context *context,
2201 GLenum source,
2202 GLenum type,
2203 GLenum severity,
2204 GLsizei count,
2205 const GLuint *ids,
2206 GLboolean enabled)
2207 {
2208 if (!context->getExtensions().debug)
2209 {
2210 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2211 return false;
2212 }
2213
2214 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
2215 {
2216 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2217 return false;
2218 }
2219
2220 if (!ValidDebugType(type) && type != GL_DONT_CARE)
2221 {
2222 context->validationError(GL_INVALID_ENUM, kInvalidDebugType);
2223 return false;
2224 }
2225
2226 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
2227 {
2228 context->validationError(GL_INVALID_ENUM, kInvalidDebugSeverity);
2229 return false;
2230 }
2231
2232 if (count > 0)
2233 {
2234 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
2235 {
2236 context->validationError(GL_INVALID_OPERATION, kInvalidDebugSourceType);
2237 return false;
2238 }
2239
2240 if (severity != GL_DONT_CARE)
2241 {
2242 context->validationError(GL_INVALID_OPERATION, kInvalidDebugSeverity);
2243 return false;
2244 }
2245 }
2246
2247 return true;
2248 }
2249
ValidateDebugMessageInsertKHR(const Context * context,GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * buf)2250 bool ValidateDebugMessageInsertKHR(const Context *context,
2251 GLenum source,
2252 GLenum type,
2253 GLuint id,
2254 GLenum severity,
2255 GLsizei length,
2256 const GLchar *buf)
2257 {
2258 if (!context->getExtensions().debug)
2259 {
2260 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2261 return false;
2262 }
2263
2264 if (!context->getState().getDebug().isOutputEnabled())
2265 {
2266 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2267 // not generate an error.
2268 return false;
2269 }
2270
2271 if (!ValidDebugSeverity(severity))
2272 {
2273 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2274 return false;
2275 }
2276
2277 if (!ValidDebugType(type))
2278 {
2279 context->validationError(GL_INVALID_ENUM, kInvalidDebugType);
2280 return false;
2281 }
2282
2283 if (!ValidDebugSource(source, true))
2284 {
2285 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2286 return false;
2287 }
2288
2289 size_t messageLength = (length < 0) ? strlen(buf) : length;
2290 if (messageLength > context->getExtensions().maxDebugMessageLength)
2291 {
2292 context->validationError(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
2293 return false;
2294 }
2295
2296 return true;
2297 }
2298
ValidateDebugMessageCallbackKHR(const Context * context,GLDEBUGPROCKHR callback,const void * userParam)2299 bool ValidateDebugMessageCallbackKHR(const Context *context,
2300 GLDEBUGPROCKHR callback,
2301 const void *userParam)
2302 {
2303 if (!context->getExtensions().debug)
2304 {
2305 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2306 return false;
2307 }
2308
2309 return true;
2310 }
2311
ValidateGetDebugMessageLogKHR(const Context * context,GLuint count,GLsizei bufSize,const GLenum * sources,const GLenum * types,const GLuint * ids,const GLenum * severities,const GLsizei * lengths,const GLchar * messageLog)2312 bool ValidateGetDebugMessageLogKHR(const Context *context,
2313 GLuint count,
2314 GLsizei bufSize,
2315 const GLenum *sources,
2316 const GLenum *types,
2317 const GLuint *ids,
2318 const GLenum *severities,
2319 const GLsizei *lengths,
2320 const GLchar *messageLog)
2321 {
2322 if (!context->getExtensions().debug)
2323 {
2324 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2325 return false;
2326 }
2327
2328 if (bufSize < 0 && messageLog != nullptr)
2329 {
2330 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2331 return false;
2332 }
2333
2334 return true;
2335 }
2336
ValidatePushDebugGroupKHR(const Context * context,GLenum source,GLuint id,GLsizei length,const GLchar * message)2337 bool ValidatePushDebugGroupKHR(const Context *context,
2338 GLenum source,
2339 GLuint id,
2340 GLsizei length,
2341 const GLchar *message)
2342 {
2343 if (!context->getExtensions().debug)
2344 {
2345 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2346 return false;
2347 }
2348
2349 if (!ValidDebugSource(source, true))
2350 {
2351 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2352 return false;
2353 }
2354
2355 size_t messageLength = (length < 0) ? strlen(message) : length;
2356 if (messageLength > context->getExtensions().maxDebugMessageLength)
2357 {
2358 context->validationError(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
2359 return false;
2360 }
2361
2362 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
2363 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2364 {
2365 context->validationError(GL_STACK_OVERFLOW, kExceedsMaxDebugGroupStackDepth);
2366 return false;
2367 }
2368
2369 return true;
2370 }
2371
ValidatePopDebugGroupKHR(const Context * context)2372 bool ValidatePopDebugGroupKHR(const Context *context)
2373 {
2374 if (!context->getExtensions().debug)
2375 {
2376 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2377 return false;
2378 }
2379
2380 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
2381 if (currentStackSize <= 1)
2382 {
2383 context->validationError(GL_STACK_UNDERFLOW, kCannotPopDefaultDebugGroup);
2384 return false;
2385 }
2386
2387 return true;
2388 }
2389
ValidateObjectIdentifierAndName(const Context * context,GLenum identifier,GLuint name)2390 static bool ValidateObjectIdentifierAndName(const Context *context, GLenum identifier, GLuint name)
2391 {
2392 switch (identifier)
2393 {
2394 case GL_BUFFER:
2395 if (context->getBuffer({name}) == nullptr)
2396 {
2397 context->validationError(GL_INVALID_VALUE, kInvalidBufferName);
2398 return false;
2399 }
2400 return true;
2401
2402 case GL_SHADER:
2403 if (context->getShader({name}) == nullptr)
2404 {
2405 context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
2406 return false;
2407 }
2408 return true;
2409
2410 case GL_PROGRAM:
2411 if (context->getProgramNoResolveLink({name}) == nullptr)
2412 {
2413 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
2414 return false;
2415 }
2416 return true;
2417
2418 case GL_VERTEX_ARRAY:
2419 if (context->getVertexArray({name}) == nullptr)
2420 {
2421 context->validationError(GL_INVALID_VALUE, kInvalidVertexArrayName);
2422 return false;
2423 }
2424 return true;
2425
2426 case GL_QUERY:
2427 if (context->getQuery({name}) == nullptr)
2428 {
2429 context->validationError(GL_INVALID_VALUE, kInvalidQueryName);
2430 return false;
2431 }
2432 return true;
2433
2434 case GL_TRANSFORM_FEEDBACK:
2435 if (context->getTransformFeedback({name}) == nullptr)
2436 {
2437 context->validationError(GL_INVALID_VALUE, kInvalidTransformFeedbackName);
2438 return false;
2439 }
2440 return true;
2441
2442 case GL_SAMPLER:
2443 if (context->getSampler({name}) == nullptr)
2444 {
2445 context->validationError(GL_INVALID_VALUE, kInvalidSamplerName);
2446 return false;
2447 }
2448 return true;
2449
2450 case GL_TEXTURE:
2451 if (context->getTexture({name}) == nullptr)
2452 {
2453 context->validationError(GL_INVALID_VALUE, kInvalidTextureName);
2454 return false;
2455 }
2456 return true;
2457
2458 case GL_RENDERBUFFER:
2459 if (!context->isRenderbuffer({name}))
2460 {
2461 context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferName);
2462 return false;
2463 }
2464 return true;
2465
2466 case GL_FRAMEBUFFER:
2467 if (context->getFramebuffer({name}) == nullptr)
2468 {
2469 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferName);
2470 return false;
2471 }
2472 return true;
2473
2474 case GL_PROGRAM_PIPELINE:
2475 if (context->getProgramPipeline({name}) == nullptr)
2476 {
2477 context->validationError(GL_INVALID_VALUE, kInvalidProgramPipelineName);
2478 return false;
2479 }
2480 return true;
2481
2482 default:
2483 context->validationError(GL_INVALID_ENUM, kInvalidIndentifier);
2484 return false;
2485 }
2486 }
2487
ValidateLabelLength(const Context * context,GLsizei length,const GLchar * label)2488 static bool ValidateLabelLength(const Context *context, GLsizei length, const GLchar *label)
2489 {
2490 size_t labelLength = 0;
2491
2492 if (length < 0)
2493 {
2494 if (label != nullptr)
2495 {
2496 labelLength = strlen(label);
2497 }
2498 }
2499 else
2500 {
2501 labelLength = static_cast<size_t>(length);
2502 }
2503
2504 if (labelLength > context->getExtensions().maxLabelLength)
2505 {
2506 context->validationError(GL_INVALID_VALUE, kExceedsMaxLabelLength);
2507 return false;
2508 }
2509
2510 return true;
2511 }
2512
ValidateObjectLabelKHR(const Context * context,GLenum identifier,GLuint name,GLsizei length,const GLchar * label)2513 bool ValidateObjectLabelKHR(const Context *context,
2514 GLenum identifier,
2515 GLuint name,
2516 GLsizei length,
2517 const GLchar *label)
2518 {
2519 if (!context->getExtensions().debug)
2520 {
2521 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2522 return false;
2523 }
2524
2525 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2526 {
2527 return false;
2528 }
2529
2530 if (!ValidateLabelLength(context, length, label))
2531 {
2532 return false;
2533 }
2534
2535 return true;
2536 }
2537
ValidateGetObjectLabelKHR(const Context * context,GLenum identifier,GLuint name,GLsizei bufSize,const GLsizei * length,const GLchar * label)2538 bool ValidateGetObjectLabelKHR(const Context *context,
2539 GLenum identifier,
2540 GLuint name,
2541 GLsizei bufSize,
2542 const GLsizei *length,
2543 const GLchar *label)
2544 {
2545 if (!context->getExtensions().debug)
2546 {
2547 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2548 return false;
2549 }
2550
2551 if (bufSize < 0)
2552 {
2553 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2554 return false;
2555 }
2556
2557 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2558 {
2559 return false;
2560 }
2561
2562 return true;
2563 }
2564
ValidateObjectPtrName(const Context * context,const void * ptr)2565 static bool ValidateObjectPtrName(const Context *context, const void *ptr)
2566 {
2567 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2568 {
2569 context->validationError(GL_INVALID_VALUE, kInvalidSyncPointer);
2570 return false;
2571 }
2572
2573 return true;
2574 }
2575
ValidateObjectPtrLabelKHR(const Context * context,const void * ptr,GLsizei length,const GLchar * label)2576 bool ValidateObjectPtrLabelKHR(const Context *context,
2577 const void *ptr,
2578 GLsizei length,
2579 const GLchar *label)
2580 {
2581 if (!context->getExtensions().debug)
2582 {
2583 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2584 return false;
2585 }
2586
2587 if (!ValidateObjectPtrName(context, ptr))
2588 {
2589 return false;
2590 }
2591
2592 if (!ValidateLabelLength(context, length, label))
2593 {
2594 return false;
2595 }
2596
2597 return true;
2598 }
2599
ValidateGetObjectPtrLabelKHR(const Context * context,const void * ptr,GLsizei bufSize,const GLsizei * length,const GLchar * label)2600 bool ValidateGetObjectPtrLabelKHR(const Context *context,
2601 const void *ptr,
2602 GLsizei bufSize,
2603 const GLsizei *length,
2604 const GLchar *label)
2605 {
2606 if (!context->getExtensions().debug)
2607 {
2608 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2609 return false;
2610 }
2611
2612 if (bufSize < 0)
2613 {
2614 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2615 return false;
2616 }
2617
2618 if (!ValidateObjectPtrName(context, ptr))
2619 {
2620 return false;
2621 }
2622
2623 return true;
2624 }
2625
ValidateGetPointervKHR(const Context * context,GLenum pname,void * const * params)2626 bool ValidateGetPointervKHR(const Context *context, GLenum pname, void *const *params)
2627 {
2628 if (!context->getExtensions().debug)
2629 {
2630 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2631 return false;
2632 }
2633
2634 // TODO: represent this in Context::getQueryParameterInfo.
2635 switch (pname)
2636 {
2637 case GL_DEBUG_CALLBACK_FUNCTION:
2638 case GL_DEBUG_CALLBACK_USER_PARAM:
2639 break;
2640
2641 default:
2642 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2643 return false;
2644 }
2645
2646 return true;
2647 }
2648
ValidateGetPointervRobustANGLERobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * params)2649 bool ValidateGetPointervRobustANGLERobustANGLE(const Context *context,
2650 GLenum pname,
2651 GLsizei bufSize,
2652 const GLsizei *length,
2653 void *const *params)
2654 {
2655 UNIMPLEMENTED();
2656 return false;
2657 }
2658
ValidateBlitFramebufferANGLE(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)2659 bool ValidateBlitFramebufferANGLE(const Context *context,
2660 GLint srcX0,
2661 GLint srcY0,
2662 GLint srcX1,
2663 GLint srcY1,
2664 GLint dstX0,
2665 GLint dstY0,
2666 GLint dstX1,
2667 GLint dstY1,
2668 GLbitfield mask,
2669 GLenum filter)
2670 {
2671 if (!context->getExtensions().framebufferBlit)
2672 {
2673 context->validationError(GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
2674 return false;
2675 }
2676
2677 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2678 {
2679 // TODO(jmadill): Determine if this should be available on other implementations.
2680 context->validationError(GL_INVALID_OPERATION, kBlitExtensionScaleOrFlip);
2681 return false;
2682 }
2683
2684 if (filter == GL_LINEAR)
2685 {
2686 context->validationError(GL_INVALID_ENUM, kBlitExtensionLinear);
2687 return false;
2688 }
2689
2690 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
2691 Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
2692
2693 if (mask & GL_COLOR_BUFFER_BIT)
2694 {
2695 const FramebufferAttachment *readColorAttachment =
2696 readFramebuffer->getReadColorAttachment();
2697 const FramebufferAttachment *drawColorAttachment =
2698 drawFramebuffer->getFirstColorAttachment();
2699
2700 if (readColorAttachment && drawColorAttachment)
2701 {
2702 if (!(readColorAttachment->type() == GL_TEXTURE &&
2703 (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D ||
2704 readColorAttachment->getTextureImageIndex().getType() ==
2705 TextureType::Rectangle)) &&
2706 readColorAttachment->type() != GL_RENDERBUFFER &&
2707 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2708 {
2709 context->validationError(GL_INVALID_OPERATION,
2710 kBlitExtensionFromInvalidAttachmentType);
2711 return false;
2712 }
2713
2714 for (size_t drawbufferIdx = 0;
2715 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
2716 {
2717 const FramebufferAttachment *attachment =
2718 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2719 if (attachment)
2720 {
2721 if (!(attachment->type() == GL_TEXTURE &&
2722 (attachment->getTextureImageIndex().getType() == TextureType::_2D ||
2723 attachment->getTextureImageIndex().getType() ==
2724 TextureType::Rectangle)) &&
2725 attachment->type() != GL_RENDERBUFFER &&
2726 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2727 {
2728 context->validationError(GL_INVALID_OPERATION,
2729 kBlitExtensionToInvalidAttachmentType);
2730 return false;
2731 }
2732
2733 // Return an error if the destination formats do not match
2734 if (!Format::EquivalentForBlit(attachment->getFormat(),
2735 readColorAttachment->getFormat()))
2736 {
2737 context->validationError(GL_INVALID_OPERATION,
2738 kBlitExtensionFormatMismatch);
2739 return false;
2740 }
2741 }
2742 }
2743
2744 GLint samples = readFramebuffer->getSamples(context);
2745 if (samples != 0 &&
2746 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2747 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2748 {
2749 context->validationError(GL_INVALID_OPERATION,
2750 kBlitExtensionMultisampledWholeBufferBlit);
2751 return false;
2752 }
2753 }
2754 }
2755
2756 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2757 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2758 for (size_t i = 0; i < 2; i++)
2759 {
2760 if (mask & masks[i])
2761 {
2762 const FramebufferAttachment *readBuffer =
2763 readFramebuffer->getAttachment(context, attachments[i]);
2764 const FramebufferAttachment *drawBuffer =
2765 drawFramebuffer->getAttachment(context, attachments[i]);
2766
2767 if (readBuffer && drawBuffer)
2768 {
2769 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2770 dstX0, dstY0, dstX1, dstY1))
2771 {
2772 // only whole-buffer copies are permitted
2773 context->validationError(GL_INVALID_OPERATION,
2774 kBlitExtensionDepthStencilWholeBufferBlit);
2775 return false;
2776 }
2777
2778 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2779 {
2780 context->validationError(GL_INVALID_OPERATION,
2781 kBlitExtensionMultisampledDepthOrStencil);
2782 return false;
2783 }
2784 }
2785 }
2786 }
2787
2788 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2789 dstX1, dstY1, mask, filter);
2790 }
2791
ValidateClear(const Context * context,GLbitfield mask)2792 bool ValidateClear(const Context *context, GLbitfield mask)
2793 {
2794 Framebuffer *fbo = context->getState().getDrawFramebuffer();
2795 const Extensions &extensions = context->getExtensions();
2796
2797 if (!ValidateFramebufferComplete(context, fbo))
2798 {
2799 return false;
2800 }
2801
2802 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2803 {
2804 context->validationError(GL_INVALID_VALUE, kInvalidClearMask);
2805 return false;
2806 }
2807
2808 if (extensions.webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2809 {
2810 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2811 GL_SIGNED_NORMALIZED};
2812
2813 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
2814 drawBufferIdx++)
2815 {
2816 if (!ValidateWebGLFramebufferAttachmentClearType(
2817 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2818 {
2819 return false;
2820 }
2821 }
2822 }
2823
2824 if ((extensions.multiview || extensions.multiview2) && extensions.disjointTimerQuery)
2825 {
2826 const State &state = context->getState();
2827 Framebuffer *framebuffer = state.getDrawFramebuffer();
2828 if (framebuffer->getNumViews() > 1 && state.isQueryActive(QueryType::TimeElapsed))
2829 {
2830 context->validationError(GL_INVALID_OPERATION, kMultiviewTimerQuery);
2831 return false;
2832 }
2833 }
2834
2835 return true;
2836 }
2837
ValidateDrawBuffersEXT(const Context * context,GLsizei n,const GLenum * bufs)2838 bool ValidateDrawBuffersEXT(const Context *context, GLsizei n, const GLenum *bufs)
2839 {
2840 if (!context->getExtensions().drawBuffers)
2841 {
2842 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2843 return false;
2844 }
2845
2846 return ValidateDrawBuffersBase(context, n, bufs);
2847 }
2848
ValidateTexImage2D(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * pixels)2849 bool ValidateTexImage2D(const Context *context,
2850 TextureTarget target,
2851 GLint level,
2852 GLint internalformat,
2853 GLsizei width,
2854 GLsizei height,
2855 GLint border,
2856 GLenum format,
2857 GLenum type,
2858 const void *pixels)
2859 {
2860 if (context->getClientMajorVersion() < 3)
2861 {
2862 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2863 0, 0, width, height, border, format, type, -1, pixels);
2864 }
2865
2866 ASSERT(context->getClientMajorVersion() >= 3);
2867 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2868 0, 0, width, height, 1, border, format, type, -1,
2869 pixels);
2870 }
2871
ValidateTexImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2872 bool ValidateTexImage2DRobustANGLE(const Context *context,
2873 TextureTarget target,
2874 GLint level,
2875 GLint internalformat,
2876 GLsizei width,
2877 GLsizei height,
2878 GLint border,
2879 GLenum format,
2880 GLenum type,
2881 GLsizei bufSize,
2882 const void *pixels)
2883 {
2884 if (!ValidateRobustEntryPoint(context, bufSize))
2885 {
2886 return false;
2887 }
2888
2889 if (context->getClientMajorVersion() < 3)
2890 {
2891 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2892 0, 0, width, height, border, format, type, bufSize,
2893 pixels);
2894 }
2895
2896 ASSERT(context->getClientMajorVersion() >= 3);
2897 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2898 0, 0, width, height, 1, border, format, type, bufSize,
2899 pixels);
2900 }
2901
ValidateTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)2902 bool ValidateTexSubImage2D(const Context *context,
2903 TextureTarget target,
2904 GLint level,
2905 GLint xoffset,
2906 GLint yoffset,
2907 GLsizei width,
2908 GLsizei height,
2909 GLenum format,
2910 GLenum type,
2911 const void *pixels)
2912 {
2913
2914 if (context->getClientMajorVersion() < 3)
2915 {
2916 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2917 yoffset, width, height, 0, format, type, -1, pixels);
2918 }
2919
2920 ASSERT(context->getClientMajorVersion() >= 3);
2921 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2922 yoffset, 0, width, height, 1, 0, format, type, -1,
2923 pixels);
2924 }
2925
ValidateTexSubImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2926 bool ValidateTexSubImage2DRobustANGLE(const Context *context,
2927 TextureTarget target,
2928 GLint level,
2929 GLint xoffset,
2930 GLint yoffset,
2931 GLsizei width,
2932 GLsizei height,
2933 GLenum format,
2934 GLenum type,
2935 GLsizei bufSize,
2936 const void *pixels)
2937 {
2938 if (!ValidateRobustEntryPoint(context, bufSize))
2939 {
2940 return false;
2941 }
2942
2943 if (context->getClientMajorVersion() < 3)
2944 {
2945 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2946 yoffset, width, height, 0, format, type, bufSize,
2947 pixels);
2948 }
2949
2950 ASSERT(context->getClientMajorVersion() >= 3);
2951 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2952 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2953 pixels);
2954 }
2955
ValidateTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)2956 bool ValidateTexSubImage3DOES(const Context *context,
2957 TextureTarget target,
2958 GLint level,
2959 GLint xoffset,
2960 GLint yoffset,
2961 GLint zoffset,
2962 GLsizei width,
2963 GLsizei height,
2964 GLsizei depth,
2965 GLenum format,
2966 GLenum type,
2967 const void *pixels)
2968 {
2969 return ValidateTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width, height,
2970 depth, format, type, pixels);
2971 }
2972
ValidateCompressedTexImage2D(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const void * data)2973 bool ValidateCompressedTexImage2D(const Context *context,
2974 TextureTarget target,
2975 GLint level,
2976 GLenum internalformat,
2977 GLsizei width,
2978 GLsizei height,
2979 GLint border,
2980 GLsizei imageSize,
2981 const void *data)
2982 {
2983 if (context->getClientMajorVersion() < 3)
2984 {
2985 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
2986 0, width, height, border, GL_NONE, GL_NONE, -1, data))
2987 {
2988 return false;
2989 }
2990 }
2991 else
2992 {
2993 ASSERT(context->getClientMajorVersion() >= 3);
2994 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
2995 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
2996 data))
2997 {
2998 return false;
2999 }
3000 }
3001
3002 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
3003
3004 GLuint blockSize = 0;
3005 if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
3006 {
3007 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
3008 return false;
3009 }
3010
3011 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
3012 {
3013 context->validationError(GL_INVALID_VALUE, kCompressedTextureDimensionsMustMatchData);
3014 return false;
3015 }
3016
3017 if (target == TextureTarget::Rectangle)
3018 {
3019 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
3020 return false;
3021 }
3022
3023 return true;
3024 }
3025
ValidateCompressedTexImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)3026 bool ValidateCompressedTexImage2DRobustANGLE(const Context *context,
3027 TextureTarget target,
3028 GLint level,
3029 GLenum internalformat,
3030 GLsizei width,
3031 GLsizei height,
3032 GLint border,
3033 GLsizei imageSize,
3034 GLsizei dataSize,
3035 const void *data)
3036 {
3037 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
3038 {
3039 return false;
3040 }
3041
3042 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
3043 border, imageSize, data);
3044 }
3045
ValidateCompressedTexImage3DOES(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)3046 bool ValidateCompressedTexImage3DOES(const Context *context,
3047 TextureTarget target,
3048 GLint level,
3049 GLenum internalformat,
3050 GLsizei width,
3051 GLsizei height,
3052 GLsizei depth,
3053 GLint border,
3054 GLsizei imageSize,
3055 const void *data)
3056 {
3057 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
3058 depth, border, imageSize, data);
3059 }
3060
ValidateCompressedTexSubImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)3061 bool ValidateCompressedTexSubImage2DRobustANGLE(const Context *context,
3062 TextureTarget target,
3063 GLint level,
3064 GLint xoffset,
3065 GLint yoffset,
3066 GLsizei width,
3067 GLsizei height,
3068 GLenum format,
3069 GLsizei imageSize,
3070 GLsizei dataSize,
3071 const void *data)
3072 {
3073 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
3074 {
3075 return false;
3076 }
3077
3078 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
3079 format, imageSize, data);
3080 }
3081
ValidateCompressedTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const void * data)3082 bool ValidateCompressedTexSubImage2D(const Context *context,
3083 TextureTarget target,
3084 GLint level,
3085 GLint xoffset,
3086 GLint yoffset,
3087 GLsizei width,
3088 GLsizei height,
3089 GLenum format,
3090 GLsizei imageSize,
3091 const void *data)
3092 {
3093 if (context->getClientMajorVersion() < 3)
3094 {
3095 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
3096 yoffset, width, height, 0, format, GL_NONE, -1, data))
3097 {
3098 return false;
3099 }
3100 }
3101 else
3102 {
3103 ASSERT(context->getClientMajorVersion() >= 3);
3104 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
3105 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
3106 data))
3107 {
3108 return false;
3109 }
3110 }
3111
3112 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
3113 GLuint blockSize = 0;
3114 if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
3115 {
3116 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
3117 return false;
3118 }
3119
3120 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
3121 {
3122 context->validationError(GL_INVALID_VALUE, kInvalidCompressedImageSize);
3123 return false;
3124 }
3125
3126 return true;
3127 }
3128
ValidateCompressedTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)3129 bool ValidateCompressedTexSubImage3DOES(const Context *context,
3130 TextureTarget target,
3131 GLint level,
3132 GLint xoffset,
3133 GLint yoffset,
3134 GLint zoffset,
3135 GLsizei width,
3136 GLsizei height,
3137 GLsizei depth,
3138 GLenum format,
3139 GLsizei imageSize,
3140 const void *data)
3141 {
3142 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
3143 height, depth, format, imageSize, data);
3144 }
3145
ValidateGetBufferPointervOES(const Context * context,BufferBinding target,GLenum pname,void * const * params)3146 bool ValidateGetBufferPointervOES(const Context *context,
3147 BufferBinding target,
3148 GLenum pname,
3149 void *const *params)
3150 {
3151 if (!context->getExtensions().mapBufferOES)
3152 {
3153 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3154 return false;
3155 }
3156
3157 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
3158 }
3159
ValidateMapBufferOES(const Context * context,BufferBinding target,GLenum access)3160 bool ValidateMapBufferOES(const Context *context, BufferBinding target, GLenum access)
3161 {
3162 if (!context->getExtensions().mapBufferOES)
3163 {
3164 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3165 return false;
3166 }
3167
3168 if (!context->isValidBufferBinding(target))
3169 {
3170 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3171 return false;
3172 }
3173
3174 Buffer *buffer = context->getState().getTargetBuffer(target);
3175
3176 if (buffer == nullptr)
3177 {
3178 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
3179 return false;
3180 }
3181
3182 if (access != GL_WRITE_ONLY_OES)
3183 {
3184 context->validationError(GL_INVALID_ENUM, kInvalidAccessBits);
3185 return false;
3186 }
3187
3188 if (buffer->isMapped())
3189 {
3190 context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
3191 return false;
3192 }
3193
3194 return ValidateMapBufferBase(context, target);
3195 }
3196
ValidateUnmapBufferOES(const Context * context,BufferBinding target)3197 bool ValidateUnmapBufferOES(const Context *context, BufferBinding target)
3198 {
3199 if (!context->getExtensions().mapBufferOES)
3200 {
3201 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3202 return false;
3203 }
3204
3205 return ValidateUnmapBufferBase(context, target);
3206 }
3207
ValidateMapBufferRangeEXT(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3208 bool ValidateMapBufferRangeEXT(const Context *context,
3209 BufferBinding target,
3210 GLintptr offset,
3211 GLsizeiptr length,
3212 GLbitfield access)
3213 {
3214 if (!context->getExtensions().mapBufferRange)
3215 {
3216 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3217 return false;
3218 }
3219
3220 return ValidateMapBufferRangeBase(context, target, offset, length, access);
3221 }
3222
ValidateBufferStorageMemEXT(const Context * context,TextureType target,GLsizeiptr size,MemoryObjectID memory,GLuint64 offset)3223 bool ValidateBufferStorageMemEXT(const Context *context,
3224 TextureType target,
3225 GLsizeiptr size,
3226 MemoryObjectID memory,
3227 GLuint64 offset)
3228 {
3229 if (!context->getExtensions().memoryObject)
3230 {
3231 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3232 return false;
3233 }
3234
3235 UNIMPLEMENTED();
3236 return false;
3237 }
3238
ValidateCreateMemoryObjectsEXT(const Context * context,GLsizei n,const MemoryObjectID * memoryObjects)3239 bool ValidateCreateMemoryObjectsEXT(const Context *context,
3240 GLsizei n,
3241 const MemoryObjectID *memoryObjects)
3242 {
3243 if (!context->getExtensions().memoryObject)
3244 {
3245 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3246 return false;
3247 }
3248
3249 return ValidateGenOrDelete(context, n);
3250 }
3251
ValidateDeleteMemoryObjectsEXT(const Context * context,GLsizei n,const MemoryObjectID * memoryObjects)3252 bool ValidateDeleteMemoryObjectsEXT(const Context *context,
3253 GLsizei n,
3254 const MemoryObjectID *memoryObjects)
3255 {
3256 if (!context->getExtensions().memoryObject)
3257 {
3258 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3259 return false;
3260 }
3261
3262 return ValidateGenOrDelete(context, n);
3263 }
3264
ValidateGetMemoryObjectParameterivEXT(const Context * context,MemoryObjectID memoryObject,GLenum pname,const GLint * params)3265 bool ValidateGetMemoryObjectParameterivEXT(const Context *context,
3266 MemoryObjectID memoryObject,
3267 GLenum pname,
3268 const GLint *params)
3269 {
3270 if (!context->getExtensions().memoryObject)
3271 {
3272 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3273 return false;
3274 }
3275
3276 const MemoryObject *memory = context->getMemoryObject(memoryObject);
3277 if (memory == nullptr)
3278 {
3279 context->validationError(GL_INVALID_VALUE, kInvalidMemoryObject);
3280 }
3281
3282 if (!IsValidMemoryObjectParamater(context, pname))
3283 {
3284 context->validationError(GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
3285 return false;
3286 }
3287
3288 return true;
3289 }
3290
ValidateGetUnsignedBytevEXT(const Context * context,GLenum pname,const GLubyte * data)3291 bool ValidateGetUnsignedBytevEXT(const Context *context, GLenum pname, const GLubyte *data)
3292 {
3293 if (!context->getExtensions().memoryObject && !context->getExtensions().semaphore)
3294 {
3295 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3296 return false;
3297 }
3298
3299 UNIMPLEMENTED();
3300 return false;
3301 }
3302
ValidateGetUnsignedBytei_vEXT(const Context * context,GLenum target,GLuint index,const GLubyte * data)3303 bool ValidateGetUnsignedBytei_vEXT(const Context *context,
3304 GLenum target,
3305 GLuint index,
3306 const GLubyte *data)
3307 {
3308 if (!context->getExtensions().memoryObject && !context->getExtensions().semaphore)
3309 {
3310 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3311 return false;
3312 }
3313
3314 UNIMPLEMENTED();
3315 return false;
3316 }
3317
ValidateIsMemoryObjectEXT(const Context * context,MemoryObjectID memoryObject)3318 bool ValidateIsMemoryObjectEXT(const Context *context, MemoryObjectID memoryObject)
3319 {
3320 if (!context->getExtensions().memoryObject)
3321 {
3322 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3323 return false;
3324 }
3325
3326 return true;
3327 }
3328
ValidateMemoryObjectParameterivEXT(const Context * context,MemoryObjectID memoryObject,GLenum pname,const GLint * params)3329 bool ValidateMemoryObjectParameterivEXT(const Context *context,
3330 MemoryObjectID memoryObject,
3331 GLenum pname,
3332 const GLint *params)
3333 {
3334 if (!context->getExtensions().memoryObject)
3335 {
3336 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3337 return false;
3338 }
3339
3340 const MemoryObject *memory = context->getMemoryObject(memoryObject);
3341 if (memory == nullptr)
3342 {
3343 context->validationError(GL_INVALID_VALUE, kInvalidMemoryObject);
3344 return false;
3345 }
3346
3347 if (memory->isImmutable())
3348 {
3349 context->validationError(GL_INVALID_OPERATION, kImmutableMemoryObject);
3350 return false;
3351 }
3352
3353 if (!IsValidMemoryObjectParamater(context, pname))
3354 {
3355 context->validationError(GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
3356 return false;
3357 }
3358
3359 return true;
3360 }
3361
ValidateTexStorageMem2DEXT(const Context * context,TextureType target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,MemoryObjectID memory,GLuint64 offset)3362 bool ValidateTexStorageMem2DEXT(const Context *context,
3363 TextureType target,
3364 GLsizei levels,
3365 GLenum internalFormat,
3366 GLsizei width,
3367 GLsizei height,
3368 MemoryObjectID memory,
3369 GLuint64 offset)
3370 {
3371 if (!context->getExtensions().memoryObject)
3372 {
3373 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3374 return false;
3375 }
3376
3377 if (context->getClientMajorVersion() < 3)
3378 {
3379 return ValidateES2TexStorageParameters(context, target, levels, internalFormat, width,
3380 height);
3381 }
3382
3383 ASSERT(context->getClientMajorVersion() >= 3);
3384 return ValidateES3TexStorage2DParameters(context, target, levels, internalFormat, width, height,
3385 1);
3386 }
3387
ValidateTexStorageMem3DEXT(const Context * context,TextureType target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,MemoryObjectID memory,GLuint64 offset)3388 bool ValidateTexStorageMem3DEXT(const Context *context,
3389 TextureType target,
3390 GLsizei levels,
3391 GLenum internalFormat,
3392 GLsizei width,
3393 GLsizei height,
3394 GLsizei depth,
3395 MemoryObjectID memory,
3396 GLuint64 offset)
3397 {
3398 if (!context->getExtensions().memoryObject)
3399 {
3400 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3401 return false;
3402 }
3403
3404 UNIMPLEMENTED();
3405 return false;
3406 }
3407
ValidateImportMemoryFdEXT(const Context * context,MemoryObjectID memory,GLuint64 size,HandleType handleType,GLint fd)3408 bool ValidateImportMemoryFdEXT(const Context *context,
3409 MemoryObjectID memory,
3410 GLuint64 size,
3411 HandleType handleType,
3412 GLint fd)
3413 {
3414 if (!context->getExtensions().memoryObjectFd)
3415 {
3416 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3417 return false;
3418 }
3419
3420 switch (handleType)
3421 {
3422 case HandleType::OpaqueFd:
3423 break;
3424 default:
3425 context->validationError(GL_INVALID_ENUM, kInvalidHandleType);
3426 return false;
3427 }
3428
3429 return true;
3430 }
3431
ValidateImportMemoryZirconHandleANGLE(const Context * context,MemoryObjectID memory,GLuint64 size,HandleType handleType,GLuint handle)3432 bool ValidateImportMemoryZirconHandleANGLE(const Context *context,
3433 MemoryObjectID memory,
3434 GLuint64 size,
3435 HandleType handleType,
3436 GLuint handle)
3437 {
3438 if (!context->getExtensions().memoryObjectFuchsiaANGLE)
3439 {
3440 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3441 return false;
3442 }
3443
3444 switch (handleType)
3445 {
3446 case HandleType::ZirconVmo:
3447 break;
3448 default:
3449 context->validationError(GL_INVALID_ENUM, kInvalidHandleType);
3450 return false;
3451 }
3452
3453 return true;
3454 }
3455
ValidateDeleteSemaphoresEXT(const Context * context,GLsizei n,const SemaphoreID * semaphores)3456 bool ValidateDeleteSemaphoresEXT(const Context *context, GLsizei n, const SemaphoreID *semaphores)
3457 {
3458 if (!context->getExtensions().semaphore)
3459 {
3460 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3461 return false;
3462 }
3463
3464 return ValidateGenOrDelete(context, n);
3465 }
3466
ValidateGenSemaphoresEXT(const Context * context,GLsizei n,const SemaphoreID * semaphores)3467 bool ValidateGenSemaphoresEXT(const Context *context, GLsizei n, const SemaphoreID *semaphores)
3468 {
3469 if (!context->getExtensions().semaphore)
3470 {
3471 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3472 return false;
3473 }
3474
3475 return ValidateGenOrDelete(context, n);
3476 }
3477
ValidateGetSemaphoreParameterui64vEXT(const Context * context,SemaphoreID semaphore,GLenum pname,const GLuint64 * params)3478 bool ValidateGetSemaphoreParameterui64vEXT(const Context *context,
3479 SemaphoreID semaphore,
3480 GLenum pname,
3481 const GLuint64 *params)
3482 {
3483 if (!context->getExtensions().semaphore)
3484 {
3485 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3486 return false;
3487 }
3488
3489 UNIMPLEMENTED();
3490 return false;
3491 }
3492
ValidateIsSemaphoreEXT(const Context * context,SemaphoreID semaphore)3493 bool ValidateIsSemaphoreEXT(const Context *context, SemaphoreID semaphore)
3494 {
3495 if (!context->getExtensions().semaphore)
3496 {
3497 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3498 return false;
3499 }
3500
3501 return true;
3502 }
3503
ValidateSemaphoreParameterui64vEXT(const Context * context,SemaphoreID semaphore,GLenum pname,const GLuint64 * params)3504 bool ValidateSemaphoreParameterui64vEXT(const Context *context,
3505 SemaphoreID semaphore,
3506 GLenum pname,
3507 const GLuint64 *params)
3508 {
3509 if (!context->getExtensions().semaphore)
3510 {
3511 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3512 return false;
3513 }
3514
3515 UNIMPLEMENTED();
3516 return false;
3517 }
3518
ValidateSignalSemaphoreEXT(const Context * context,SemaphoreID semaphore,GLuint numBufferBarriers,const BufferID * buffers,GLuint numTextureBarriers,const TextureID * textures,const GLenum * dstLayouts)3519 bool ValidateSignalSemaphoreEXT(const Context *context,
3520 SemaphoreID semaphore,
3521 GLuint numBufferBarriers,
3522 const BufferID *buffers,
3523 GLuint numTextureBarriers,
3524 const TextureID *textures,
3525 const GLenum *dstLayouts)
3526 {
3527 if (!context->getExtensions().semaphore)
3528 {
3529 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3530 return false;
3531 }
3532
3533 for (GLuint i = 0; i < numTextureBarriers; ++i)
3534 {
3535 if (!IsValidImageLayout(FromGLenum<ImageLayout>(dstLayouts[i])))
3536 {
3537 context->validationError(GL_INVALID_ENUM, kInvalidImageLayout);
3538 return false;
3539 }
3540 }
3541
3542 return true;
3543 }
3544
ValidateWaitSemaphoreEXT(const Context * context,SemaphoreID semaphore,GLuint numBufferBarriers,const BufferID * buffers,GLuint numTextureBarriers,const TextureID * textures,const GLenum * srcLayouts)3545 bool ValidateWaitSemaphoreEXT(const Context *context,
3546 SemaphoreID semaphore,
3547 GLuint numBufferBarriers,
3548 const BufferID *buffers,
3549 GLuint numTextureBarriers,
3550 const TextureID *textures,
3551 const GLenum *srcLayouts)
3552 {
3553 if (!context->getExtensions().semaphore)
3554 {
3555 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3556 return false;
3557 }
3558
3559 for (GLuint i = 0; i < numTextureBarriers; ++i)
3560 {
3561 if (!IsValidImageLayout(FromGLenum<ImageLayout>(srcLayouts[i])))
3562 {
3563 context->validationError(GL_INVALID_ENUM, kInvalidImageLayout);
3564 return false;
3565 }
3566 }
3567
3568 return true;
3569 }
3570
ValidateImportSemaphoreFdEXT(const Context * context,SemaphoreID semaphore,HandleType handleType,GLint fd)3571 bool ValidateImportSemaphoreFdEXT(const Context *context,
3572 SemaphoreID semaphore,
3573 HandleType handleType,
3574 GLint fd)
3575 {
3576 if (!context->getExtensions().semaphoreFd)
3577 {
3578 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3579 return false;
3580 }
3581
3582 switch (handleType)
3583 {
3584 case HandleType::OpaqueFd:
3585 break;
3586 default:
3587 context->validationError(GL_INVALID_ENUM, kInvalidHandleType);
3588 return false;
3589 }
3590
3591 return true;
3592 }
3593
ValidateImportSemaphoreZirconHandleANGLE(const Context * context,SemaphoreID semaphore,HandleType handleType,GLuint handle)3594 bool ValidateImportSemaphoreZirconHandleANGLE(const Context *context,
3595 SemaphoreID semaphore,
3596 HandleType handleType,
3597 GLuint handle)
3598 {
3599 if (!context->getExtensions().semaphoreFuchsiaANGLE)
3600 {
3601 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3602 return false;
3603 }
3604
3605 switch (handleType)
3606 {
3607 case HandleType::ZirconEvent:
3608 break;
3609 default:
3610 context->validationError(GL_INVALID_ENUM, kInvalidHandleType);
3611 return false;
3612 }
3613
3614 return true;
3615 }
3616
ValidateMapBufferBase(const Context * context,BufferBinding target)3617 bool ValidateMapBufferBase(const Context *context, BufferBinding target)
3618 {
3619 Buffer *buffer = context->getState().getTargetBuffer(target);
3620 ASSERT(buffer != nullptr);
3621
3622 // Check if this buffer is currently being used as a transform feedback output buffer
3623 if (context->getState().isTransformFeedbackActive())
3624 {
3625 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3626 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
3627 {
3628 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
3629 if (transformFeedbackBuffer.get() == buffer)
3630 {
3631 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3632 return false;
3633 }
3634 }
3635 }
3636
3637 if (context->getExtensions().webglCompatibility &&
3638 buffer->isBoundForTransformFeedbackAndOtherUse())
3639 {
3640 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3641 return false;
3642 }
3643
3644 return true;
3645 }
3646
ValidateFlushMappedBufferRangeEXT(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)3647 bool ValidateFlushMappedBufferRangeEXT(const Context *context,
3648 BufferBinding target,
3649 GLintptr offset,
3650 GLsizeiptr length)
3651 {
3652 if (!context->getExtensions().mapBufferRange)
3653 {
3654 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3655 return false;
3656 }
3657
3658 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
3659 }
3660
ValidateBindUniformLocationCHROMIUM(const Context * context,ShaderProgramID program,UniformLocation location,const GLchar * name)3661 bool ValidateBindUniformLocationCHROMIUM(const Context *context,
3662 ShaderProgramID program,
3663 UniformLocation location,
3664 const GLchar *name)
3665 {
3666 if (!context->getExtensions().bindUniformLocation)
3667 {
3668 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3669 return false;
3670 }
3671
3672 Program *programObject = GetValidProgram(context, program);
3673 if (!programObject)
3674 {
3675 return false;
3676 }
3677
3678 if (location.value < 0)
3679 {
3680 context->validationError(GL_INVALID_VALUE, kNegativeLocation);
3681 return false;
3682 }
3683
3684 const Caps &caps = context->getCaps();
3685 if (static_cast<long>(location.value) >=
3686 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
3687 {
3688 context->validationError(GL_INVALID_VALUE, kInvalidBindUniformLocation);
3689 return false;
3690 }
3691
3692 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3693 // shader-related entry points
3694 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
3695 {
3696 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
3697 return false;
3698 }
3699
3700 if (strncmp(name, "gl_", 3) == 0)
3701 {
3702 context->validationError(GL_INVALID_VALUE, kNameBeginsWithGL);
3703 return false;
3704 }
3705
3706 return true;
3707 }
3708
ValidateCoverageModulationCHROMIUM(const Context * context,GLenum components)3709 bool ValidateCoverageModulationCHROMIUM(const Context *context, GLenum components)
3710 {
3711 if (!context->getExtensions().framebufferMixedSamples)
3712 {
3713 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3714 return false;
3715 }
3716 switch (components)
3717 {
3718 case GL_RGB:
3719 case GL_RGBA:
3720 case GL_ALPHA:
3721 case GL_NONE:
3722 break;
3723 default:
3724 context->validationError(GL_INVALID_ENUM, kInvalidCoverageComponents);
3725 return false;
3726 }
3727
3728 return true;
3729 }
3730
ValidateCopyTextureCHROMIUM(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint internalFormat,GLenum destType,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)3731 bool ValidateCopyTextureCHROMIUM(const Context *context,
3732 TextureID sourceId,
3733 GLint sourceLevel,
3734 TextureTarget destTarget,
3735 TextureID destId,
3736 GLint destLevel,
3737 GLint internalFormat,
3738 GLenum destType,
3739 GLboolean unpackFlipY,
3740 GLboolean unpackPremultiplyAlpha,
3741 GLboolean unpackUnmultiplyAlpha)
3742 {
3743 if (!context->getExtensions().copyTexture)
3744 {
3745 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3746 return false;
3747 }
3748
3749 const Texture *source = context->getTexture(sourceId);
3750 if (source == nullptr)
3751 {
3752 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3753 return false;
3754 }
3755
3756 if (!IsValidCopyTextureSourceTarget(context, source->getType()))
3757 {
3758 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3759 return false;
3760 }
3761
3762 TextureType sourceType = source->getType();
3763 ASSERT(sourceType != TextureType::CubeMap);
3764 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
3765
3766 if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
3767 {
3768 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
3769 return false;
3770 }
3771
3772 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3773 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3774 if (sourceWidth == 0 || sourceHeight == 0)
3775 {
3776 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3777 return false;
3778 }
3779
3780 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3781 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
3782 {
3783 context->validationError(GL_INVALID_OPERATION, kInvalidSourceTextureInternalFormat);
3784 return false;
3785 }
3786
3787 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3788 {
3789 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3790 return false;
3791 }
3792
3793 const Texture *dest = context->getTexture(destId);
3794 if (dest == nullptr)
3795 {
3796 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3797 return false;
3798 }
3799
3800 if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
3801 {
3802 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3803 return false;
3804 }
3805
3806 if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, sourceWidth,
3807 sourceHeight, false))
3808 {
3809 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3810 return false;
3811 }
3812
3813 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3814 {
3815 return false;
3816 }
3817
3818 if (dest->getType() == TextureType::CubeMap && sourceWidth != sourceHeight)
3819 {
3820 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
3821 return false;
3822 }
3823
3824 if (dest->getImmutableFormat())
3825 {
3826 context->validationError(GL_INVALID_OPERATION, kDestinationImmutable);
3827 return false;
3828 }
3829
3830 return true;
3831 }
3832
ValidateCopySubTextureCHROMIUM(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)3833 bool ValidateCopySubTextureCHROMIUM(const Context *context,
3834 TextureID sourceId,
3835 GLint sourceLevel,
3836 TextureTarget destTarget,
3837 TextureID destId,
3838 GLint destLevel,
3839 GLint xoffset,
3840 GLint yoffset,
3841 GLint x,
3842 GLint y,
3843 GLsizei width,
3844 GLsizei height,
3845 GLboolean unpackFlipY,
3846 GLboolean unpackPremultiplyAlpha,
3847 GLboolean unpackUnmultiplyAlpha)
3848 {
3849 if (!context->getExtensions().copyTexture)
3850 {
3851 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3852 return false;
3853 }
3854
3855 const Texture *source = context->getTexture(sourceId);
3856 if (source == nullptr)
3857 {
3858 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3859 return false;
3860 }
3861
3862 if (!IsValidCopyTextureSourceTarget(context, source->getType()))
3863 {
3864 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureType);
3865 return false;
3866 }
3867
3868 TextureType sourceType = source->getType();
3869 ASSERT(sourceType != TextureType::CubeMap);
3870 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
3871
3872 if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
3873 {
3874 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3875 return false;
3876 }
3877
3878 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3879 source->getHeight(sourceTarget, sourceLevel) == 0)
3880 {
3881 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
3882 return false;
3883 }
3884
3885 if (x < 0 || y < 0)
3886 {
3887 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3888 return false;
3889 }
3890
3891 if (width < 0 || height < 0)
3892 {
3893 context->validationError(GL_INVALID_VALUE, kNegativeSize);
3894 return false;
3895 }
3896
3897 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3898 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
3899 {
3900 context->validationError(GL_INVALID_VALUE, kSourceTextureTooSmall);
3901 return false;
3902 }
3903
3904 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3905 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
3906 {
3907 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3908 return false;
3909 }
3910
3911 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3912 {
3913 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3914 return false;
3915 }
3916
3917 const Texture *dest = context->getTexture(destId);
3918 if (dest == nullptr)
3919 {
3920 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3921 return false;
3922 }
3923
3924 if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
3925 {
3926 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3927 return false;
3928 }
3929
3930 if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, width, height,
3931 true))
3932 {
3933 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3934 return false;
3935 }
3936
3937 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3938 {
3939 context->validationError(GL_INVALID_OPERATION, kDestinationLevelNotDefined);
3940 return false;
3941 }
3942
3943 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3944 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
3945 {
3946 context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
3947 return false;
3948 }
3949
3950 if (xoffset < 0 || yoffset < 0)
3951 {
3952 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3953 return false;
3954 }
3955
3956 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3957 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
3958 {
3959 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
3960 return false;
3961 }
3962
3963 return true;
3964 }
3965
ValidateCompressedCopyTextureCHROMIUM(const Context * context,TextureID sourceId,TextureID destId)3966 bool ValidateCompressedCopyTextureCHROMIUM(const Context *context,
3967 TextureID sourceId,
3968 TextureID destId)
3969 {
3970 if (!context->getExtensions().copyCompressedTexture)
3971 {
3972 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3973 return false;
3974 }
3975
3976 const Texture *source = context->getTexture(sourceId);
3977 if (source == nullptr)
3978 {
3979 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3980 return false;
3981 }
3982
3983 if (source->getType() != TextureType::_2D)
3984 {
3985 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureType);
3986 return false;
3987 }
3988
3989 if (source->getWidth(TextureTarget::_2D, 0) == 0 ||
3990 source->getHeight(TextureTarget::_2D, 0) == 0)
3991 {
3992 context->validationError(GL_INVALID_VALUE, kSourceTextureLevelZeroDefined);
3993 return false;
3994 }
3995
3996 const Format &sourceFormat = source->getFormat(TextureTarget::_2D, 0);
3997 if (!sourceFormat.info->compressed)
3998 {
3999 context->validationError(GL_INVALID_OPERATION, kSourceTextureMustBeCompressed);
4000 return false;
4001 }
4002
4003 const Texture *dest = context->getTexture(destId);
4004 if (dest == nullptr)
4005 {
4006 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
4007 return false;
4008 }
4009
4010 if (dest->getType() != TextureType::_2D)
4011 {
4012 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
4013 return false;
4014 }
4015
4016 if (dest->getImmutableFormat())
4017 {
4018 context->validationError(GL_INVALID_OPERATION, kDestinationImmutable);
4019 return false;
4020 }
4021
4022 return true;
4023 }
4024
ValidateCreateShader(const Context * context,ShaderType type)4025 bool ValidateCreateShader(const Context *context, ShaderType type)
4026 {
4027 switch (type)
4028 {
4029 case ShaderType::Vertex:
4030 case ShaderType::Fragment:
4031 break;
4032
4033 case ShaderType::Compute:
4034 if (context->getClientVersion() < Version(3, 1))
4035 {
4036 context->validationError(GL_INVALID_ENUM, kES31Required);
4037 return false;
4038 }
4039 break;
4040
4041 case ShaderType::Geometry:
4042 if (!context->getExtensions().geometryShader)
4043 {
4044 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
4045 return false;
4046 }
4047 break;
4048 default:
4049 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
4050 return false;
4051 }
4052
4053 return true;
4054 }
4055
ValidateBufferData(const Context * context,BufferBinding target,GLsizeiptr size,const void * data,BufferUsage usage)4056 bool ValidateBufferData(const Context *context,
4057 BufferBinding target,
4058 GLsizeiptr size,
4059 const void *data,
4060 BufferUsage usage)
4061 {
4062 if (size < 0)
4063 {
4064 context->validationError(GL_INVALID_VALUE, kNegativeSize);
4065 return false;
4066 }
4067
4068 switch (usage)
4069 {
4070 case BufferUsage::StreamDraw:
4071 case BufferUsage::StaticDraw:
4072 case BufferUsage::DynamicDraw:
4073 break;
4074
4075 case BufferUsage::StreamRead:
4076 case BufferUsage::StaticRead:
4077 case BufferUsage::DynamicRead:
4078 case BufferUsage::StreamCopy:
4079 case BufferUsage::StaticCopy:
4080 case BufferUsage::DynamicCopy:
4081 if (context->getClientMajorVersion() < 3)
4082 {
4083 context->validationError(GL_INVALID_ENUM, kInvalidBufferUsage);
4084 return false;
4085 }
4086 break;
4087
4088 default:
4089 context->validationError(GL_INVALID_ENUM, kInvalidBufferUsage);
4090 return false;
4091 }
4092
4093 if (!context->isValidBufferBinding(target))
4094 {
4095 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
4096 return false;
4097 }
4098
4099 Buffer *buffer = context->getState().getTargetBuffer(target);
4100
4101 if (!buffer)
4102 {
4103 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
4104 return false;
4105 }
4106
4107 if (context->getExtensions().webglCompatibility &&
4108 buffer->isBoundForTransformFeedbackAndOtherUse())
4109 {
4110 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
4111 return false;
4112 }
4113
4114 return true;
4115 }
4116
ValidateBufferSubData(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr size,const void * data)4117 bool ValidateBufferSubData(const Context *context,
4118 BufferBinding target,
4119 GLintptr offset,
4120 GLsizeiptr size,
4121 const void *data)
4122 {
4123 if (size < 0)
4124 {
4125 context->validationError(GL_INVALID_VALUE, kNegativeSize);
4126 return false;
4127 }
4128
4129 if (offset < 0)
4130 {
4131 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
4132 return false;
4133 }
4134
4135 if (!context->isValidBufferBinding(target))
4136 {
4137 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
4138 return false;
4139 }
4140
4141 Buffer *buffer = context->getState().getTargetBuffer(target);
4142
4143 if (!buffer)
4144 {
4145 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
4146 return false;
4147 }
4148
4149 if (buffer->isMapped())
4150 {
4151 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
4152 return false;
4153 }
4154
4155 if (context->getExtensions().webglCompatibility &&
4156 buffer->isBoundForTransformFeedbackAndOtherUse())
4157 {
4158 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
4159 return false;
4160 }
4161
4162 // Check for possible overflow of size + offset
4163 angle::CheckedNumeric<size_t> checkedSize(size);
4164 checkedSize += offset;
4165 if (!checkedSize.IsValid())
4166 {
4167 context->validationError(GL_INVALID_VALUE, kParamOverflow);
4168 return false;
4169 }
4170
4171 if (size + offset > buffer->getSize())
4172 {
4173 context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
4174 return false;
4175 }
4176
4177 return true;
4178 }
4179
ValidateRequestExtensionANGLE(const Context * context,const GLchar * name)4180 bool ValidateRequestExtensionANGLE(const Context *context, const GLchar *name)
4181 {
4182 if (!context->getExtensions().requestExtension)
4183 {
4184 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4185 return false;
4186 }
4187
4188 if (!context->isExtensionRequestable(name))
4189 {
4190 context->validationError(GL_INVALID_OPERATION, kExtensionNotRequestable);
4191 return false;
4192 }
4193
4194 return true;
4195 }
4196
ValidateDisableExtensionANGLE(const Context * context,const GLchar * name)4197 bool ValidateDisableExtensionANGLE(const Context *context, const GLchar *name)
4198 {
4199 if (!context->getExtensions().requestExtension)
4200 {
4201 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4202 return false;
4203 }
4204
4205 if (!context->isExtensionDisablable(name))
4206 {
4207 context->validationError(GL_INVALID_OPERATION, kExtensionNotDisablable);
4208 return false;
4209 }
4210
4211 return true;
4212 }
4213
ValidateActiveTexture(const Context * context,GLenum texture)4214 bool ValidateActiveTexture(const Context *context, GLenum texture)
4215 {
4216 if (context->getClientMajorVersion() < 2)
4217 {
4218 return ValidateMultitextureUnit(context, texture);
4219 }
4220
4221 if (texture < GL_TEXTURE0 ||
4222 texture >
4223 GL_TEXTURE0 + static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits) - 1)
4224 {
4225 context->validationError(GL_INVALID_ENUM, kInvalidCombinedImageUnit);
4226 return false;
4227 }
4228
4229 return true;
4230 }
4231
ValidateAttachShader(const Context * context,ShaderProgramID program,ShaderProgramID shader)4232 bool ValidateAttachShader(const Context *context, ShaderProgramID program, ShaderProgramID shader)
4233 {
4234 Program *programObject = GetValidProgram(context, program);
4235 if (!programObject)
4236 {
4237 return false;
4238 }
4239
4240 Shader *shaderObject = GetValidShader(context, shader);
4241 if (!shaderObject)
4242 {
4243 return false;
4244 }
4245
4246 if (programObject->getAttachedShader(shaderObject->getType()) &&
4247 !programObject->getState().isShaderMarkedForDetach(shaderObject->getType()))
4248 {
4249 context->validationError(GL_INVALID_OPERATION, kShaderAttachmentHasShader);
4250 return false;
4251 }
4252
4253 return true;
4254 }
4255
ValidateBindAttribLocation(const Context * context,ShaderProgramID program,GLuint index,const GLchar * name)4256 bool ValidateBindAttribLocation(const Context *context,
4257 ShaderProgramID program,
4258 GLuint index,
4259 const GLchar *name)
4260 {
4261 if (index >= MAX_VERTEX_ATTRIBS)
4262 {
4263 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
4264 return false;
4265 }
4266
4267 if (strncmp(name, "gl_", 3) == 0)
4268 {
4269 context->validationError(GL_INVALID_OPERATION, kNameBeginsWithGL);
4270 return false;
4271 }
4272
4273 if (context->isWebGL())
4274 {
4275 const size_t length = strlen(name);
4276
4277 if (!IsValidESSLString(name, length))
4278 {
4279 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4280 // for shader-related entry points
4281 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
4282 return false;
4283 }
4284
4285 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4286 {
4287 return false;
4288 }
4289 }
4290
4291 return GetValidProgram(context, program) != nullptr;
4292 }
4293
ValidateBindFramebuffer(const Context * context,GLenum target,FramebufferID framebuffer)4294 bool ValidateBindFramebuffer(const Context *context, GLenum target, FramebufferID framebuffer)
4295 {
4296 if (!ValidFramebufferTarget(context, target))
4297 {
4298 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
4299 return false;
4300 }
4301
4302 if (!context->getState().isBindGeneratesResourceEnabled() &&
4303 !context->isFramebufferGenerated(framebuffer))
4304 {
4305 context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
4306 return false;
4307 }
4308
4309 return true;
4310 }
4311
ValidateBindRenderbuffer(const Context * context,GLenum target,RenderbufferID renderbuffer)4312 bool ValidateBindRenderbuffer(const Context *context, GLenum target, RenderbufferID renderbuffer)
4313 {
4314 if (target != GL_RENDERBUFFER)
4315 {
4316 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
4317 return false;
4318 }
4319
4320 if (!context->getState().isBindGeneratesResourceEnabled() &&
4321 !context->isRenderbufferGenerated(renderbuffer))
4322 {
4323 context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
4324 return false;
4325 }
4326
4327 return true;
4328 }
4329
ValidBlendEquationMode(const Context * context,GLenum mode)4330 static bool ValidBlendEquationMode(const Context *context, GLenum mode)
4331 {
4332 switch (mode)
4333 {
4334 case GL_FUNC_ADD:
4335 case GL_FUNC_SUBTRACT:
4336 case GL_FUNC_REVERSE_SUBTRACT:
4337 return true;
4338
4339 case GL_MIN:
4340 case GL_MAX:
4341 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
4342
4343 default:
4344 return false;
4345 }
4346 }
4347
ValidateBlendColor(const Context * context,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)4348 bool ValidateBlendColor(const Context *context,
4349 GLfloat red,
4350 GLfloat green,
4351 GLfloat blue,
4352 GLfloat alpha)
4353 {
4354 return true;
4355 }
4356
ValidateBlendEquation(const Context * context,GLenum mode)4357 bool ValidateBlendEquation(const Context *context, GLenum mode)
4358 {
4359 if (!ValidBlendEquationMode(context, mode))
4360 {
4361 context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
4362 return false;
4363 }
4364
4365 return true;
4366 }
4367
ValidateBlendEquationSeparate(const Context * context,GLenum modeRGB,GLenum modeAlpha)4368 bool ValidateBlendEquationSeparate(const Context *context, GLenum modeRGB, GLenum modeAlpha)
4369 {
4370 if (!ValidBlendEquationMode(context, modeRGB))
4371 {
4372 context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
4373 return false;
4374 }
4375
4376 if (!ValidBlendEquationMode(context, modeAlpha))
4377 {
4378 context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
4379 return false;
4380 }
4381
4382 return true;
4383 }
4384
ValidateBlendFunc(const Context * context,GLenum sfactor,GLenum dfactor)4385 bool ValidateBlendFunc(const Context *context, GLenum sfactor, GLenum dfactor)
4386 {
4387 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4388 }
4389
ValidateBlendFuncSeparate(const Context * context,GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha)4390 bool ValidateBlendFuncSeparate(const Context *context,
4391 GLenum srcRGB,
4392 GLenum dstRGB,
4393 GLenum srcAlpha,
4394 GLenum dstAlpha)
4395 {
4396 if (!ValidSrcBlendFunc(context, srcRGB))
4397 {
4398 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
4399 return false;
4400 }
4401
4402 if (!ValidDstBlendFunc(context, dstRGB))
4403 {
4404 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
4405 return false;
4406 }
4407
4408 if (!ValidSrcBlendFunc(context, srcAlpha))
4409 {
4410 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
4411 return false;
4412 }
4413
4414 if (!ValidDstBlendFunc(context, dstAlpha))
4415 {
4416 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
4417 return false;
4418 }
4419
4420 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4421 context->getExtensions().webglCompatibility)
4422 {
4423 bool constantColorUsed =
4424 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4425 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4426
4427 bool constantAlphaUsed =
4428 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4429 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4430
4431 if (constantColorUsed && constantAlphaUsed)
4432 {
4433 if (context->getExtensions().webglCompatibility)
4434 {
4435 context->validationError(GL_INVALID_OPERATION, kInvalidConstantColor);
4436 return false;
4437 }
4438
4439 WARN() << kConstantColorAlphaLimitation;
4440 context->validationError(GL_INVALID_OPERATION, kConstantColorAlphaLimitation);
4441 return false;
4442 }
4443 }
4444
4445 return true;
4446 }
4447
ValidateGetString(const Context * context,GLenum name)4448 bool ValidateGetString(const Context *context, GLenum name)
4449 {
4450 switch (name)
4451 {
4452 case GL_VENDOR:
4453 case GL_RENDERER:
4454 case GL_VERSION:
4455 case GL_SHADING_LANGUAGE_VERSION:
4456 case GL_EXTENSIONS:
4457 break;
4458
4459 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4460 if (!context->getExtensions().requestExtension)
4461 {
4462 context->validationError(GL_INVALID_ENUM, kInvalidName);
4463 return false;
4464 }
4465 break;
4466
4467 default:
4468 context->validationError(GL_INVALID_ENUM, kInvalidName);
4469 return false;
4470 }
4471
4472 return true;
4473 }
4474
ValidateLineWidth(const Context * context,GLfloat width)4475 bool ValidateLineWidth(const Context *context, GLfloat width)
4476 {
4477 if (width <= 0.0f || isNaN(width))
4478 {
4479 context->validationError(GL_INVALID_VALUE, kInvalidWidth);
4480 return false;
4481 }
4482
4483 return true;
4484 }
4485
ValidateDepthRangef(const Context * context,GLfloat zNear,GLfloat zFar)4486 bool ValidateDepthRangef(const Context *context, GLfloat zNear, GLfloat zFar)
4487 {
4488 if (context->getExtensions().webglCompatibility && zNear > zFar)
4489 {
4490 context->validationError(GL_INVALID_OPERATION, kInvalidDepthRange);
4491 return false;
4492 }
4493
4494 return true;
4495 }
4496
ValidateRenderbufferStorage(const Context * context,GLenum target,GLenum internalformat,GLsizei width,GLsizei height)4497 bool ValidateRenderbufferStorage(const Context *context,
4498 GLenum target,
4499 GLenum internalformat,
4500 GLsizei width,
4501 GLsizei height)
4502 {
4503 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4504 height);
4505 }
4506
ValidateRenderbufferStorageMultisampleANGLE(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)4507 bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context,
4508 GLenum target,
4509 GLsizei samples,
4510 GLenum internalformat,
4511 GLsizei width,
4512 GLsizei height)
4513 {
4514 if (!context->getExtensions().framebufferMultisample)
4515 {
4516 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4517 return false;
4518 }
4519
4520 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4521 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
4522 // generated.
4523 if (samples > context->getCaps().maxSamples)
4524 {
4525 context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
4526 return false;
4527 }
4528
4529 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4530 // the specified storage. This is different than ES 3.0 in which a sample number higher
4531 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4532 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4533 if (context->getClientMajorVersion() >= 3)
4534 {
4535 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4536 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4537 {
4538 context->validationError(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
4539 return false;
4540 }
4541 }
4542
4543 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4544 width, height);
4545 }
4546
ValidateCheckFramebufferStatus(const Context * context,GLenum target)4547 bool ValidateCheckFramebufferStatus(const Context *context, GLenum target)
4548 {
4549 if (!ValidFramebufferTarget(context, target))
4550 {
4551 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
4552 return false;
4553 }
4554
4555 return true;
4556 }
4557
ValidateClearColor(const Context * context,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)4558 bool ValidateClearColor(const Context *context,
4559 GLfloat red,
4560 GLfloat green,
4561 GLfloat blue,
4562 GLfloat alpha)
4563 {
4564 return true;
4565 }
4566
ValidateClearDepthf(const Context * context,GLfloat depth)4567 bool ValidateClearDepthf(const Context *context, GLfloat depth)
4568 {
4569 return true;
4570 }
4571
ValidateClearStencil(const Context * context,GLint s)4572 bool ValidateClearStencil(const Context *context, GLint s)
4573 {
4574 return true;
4575 }
4576
ValidateColorMask(const Context * context,GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)4577 bool ValidateColorMask(const Context *context,
4578 GLboolean red,
4579 GLboolean green,
4580 GLboolean blue,
4581 GLboolean alpha)
4582 {
4583 return true;
4584 }
4585
ValidateCompileShader(const Context * context,ShaderProgramID shader)4586 bool ValidateCompileShader(const Context *context, ShaderProgramID shader)
4587 {
4588 return true;
4589 }
4590
ValidateCreateProgram(const Context * context)4591 bool ValidateCreateProgram(const Context *context)
4592 {
4593 return true;
4594 }
4595
ValidateCullFace(const Context * context,CullFaceMode mode)4596 bool ValidateCullFace(const Context *context, CullFaceMode mode)
4597 {
4598 switch (mode)
4599 {
4600 case CullFaceMode::Front:
4601 case CullFaceMode::Back:
4602 case CullFaceMode::FrontAndBack:
4603 break;
4604
4605 default:
4606 context->validationError(GL_INVALID_ENUM, kInvalidCullMode);
4607 return false;
4608 }
4609
4610 return true;
4611 }
4612
ValidateDeleteProgram(const Context * context,ShaderProgramID program)4613 bool ValidateDeleteProgram(const Context *context, ShaderProgramID program)
4614 {
4615 if (program.value == 0)
4616 {
4617 return false;
4618 }
4619
4620 if (!context->getProgramResolveLink(program))
4621 {
4622 if (context->getShader(program))
4623 {
4624 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
4625 return false;
4626 }
4627 else
4628 {
4629 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
4630 return false;
4631 }
4632 }
4633
4634 return true;
4635 }
4636
ValidateDeleteShader(const Context * context,ShaderProgramID shader)4637 bool ValidateDeleteShader(const Context *context, ShaderProgramID shader)
4638 {
4639 if (shader.value == 0)
4640 {
4641 return false;
4642 }
4643
4644 if (!context->getShader(shader))
4645 {
4646 if (context->getProgramResolveLink(shader))
4647 {
4648 context->validationError(GL_INVALID_OPERATION, kInvalidShaderName);
4649 return false;
4650 }
4651 else
4652 {
4653 context->validationError(GL_INVALID_VALUE, kExpectedShaderName);
4654 return false;
4655 }
4656 }
4657
4658 return true;
4659 }
4660
ValidateDepthFunc(const Context * context,GLenum func)4661 bool ValidateDepthFunc(const Context *context, GLenum func)
4662 {
4663 switch (func)
4664 {
4665 case GL_NEVER:
4666 case GL_ALWAYS:
4667 case GL_LESS:
4668 case GL_LEQUAL:
4669 case GL_EQUAL:
4670 case GL_GREATER:
4671 case GL_GEQUAL:
4672 case GL_NOTEQUAL:
4673 break;
4674
4675 default:
4676 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4677 return false;
4678 }
4679
4680 return true;
4681 }
4682
ValidateDepthMask(const Context * context,GLboolean flag)4683 bool ValidateDepthMask(const Context *context, GLboolean flag)
4684 {
4685 return true;
4686 }
4687
ValidateDetachShader(const Context * context,ShaderProgramID program,ShaderProgramID shader)4688 bool ValidateDetachShader(const Context *context, ShaderProgramID program, ShaderProgramID shader)
4689 {
4690 Program *programObject = GetValidProgram(context, program);
4691 if (!programObject)
4692 {
4693 return false;
4694 }
4695
4696 Shader *shaderObject = GetValidShader(context, shader);
4697 if (!shaderObject)
4698 {
4699 return false;
4700 }
4701
4702 const Shader *attachedShader = programObject->getAttachedShader(shaderObject->getType());
4703 if (attachedShader != shaderObject)
4704 {
4705 context->validationError(GL_INVALID_OPERATION, kShaderToDetachMustBeAttached);
4706 return false;
4707 }
4708
4709 return true;
4710 }
4711
ValidateDisableVertexAttribArray(const Context * context,GLuint index)4712 bool ValidateDisableVertexAttribArray(const Context *context, GLuint index)
4713 {
4714 if (index >= MAX_VERTEX_ATTRIBS)
4715 {
4716 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
4717 return false;
4718 }
4719
4720 return true;
4721 }
4722
ValidateEnableVertexAttribArray(const Context * context,GLuint index)4723 bool ValidateEnableVertexAttribArray(const Context *context, GLuint index)
4724 {
4725 if (index >= MAX_VERTEX_ATTRIBS)
4726 {
4727 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
4728 return false;
4729 }
4730
4731 return true;
4732 }
4733
ValidateFinish(const Context * context)4734 bool ValidateFinish(const Context *context)
4735 {
4736 return true;
4737 }
4738
ValidateFlush(const Context * context)4739 bool ValidateFlush(const Context *context)
4740 {
4741 return true;
4742 }
4743
ValidateFrontFace(const Context * context,GLenum mode)4744 bool ValidateFrontFace(const Context *context, GLenum mode)
4745 {
4746 switch (mode)
4747 {
4748 case GL_CW:
4749 case GL_CCW:
4750 break;
4751 default:
4752 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4753 return false;
4754 }
4755
4756 return true;
4757 }
4758
ValidateGetActiveAttrib(const Context * context,ShaderProgramID program,GLuint index,GLsizei bufsize,const GLsizei * length,const GLint * size,const GLenum * type,const GLchar * name)4759 bool ValidateGetActiveAttrib(const Context *context,
4760 ShaderProgramID program,
4761 GLuint index,
4762 GLsizei bufsize,
4763 const GLsizei *length,
4764 const GLint *size,
4765 const GLenum *type,
4766 const GLchar *name)
4767 {
4768 if (bufsize < 0)
4769 {
4770 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4771 return false;
4772 }
4773
4774 Program *programObject = GetValidProgram(context, program);
4775
4776 if (!programObject)
4777 {
4778 return false;
4779 }
4780
4781 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4782 {
4783 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4784 return false;
4785 }
4786
4787 return true;
4788 }
4789
ValidateGetActiveUniform(const Context * context,ShaderProgramID program,GLuint index,GLsizei bufsize,const GLsizei * length,const GLint * size,const GLenum * type,const GLchar * name)4790 bool ValidateGetActiveUniform(const Context *context,
4791 ShaderProgramID program,
4792 GLuint index,
4793 GLsizei bufsize,
4794 const GLsizei *length,
4795 const GLint *size,
4796 const GLenum *type,
4797 const GLchar *name)
4798 {
4799 if (bufsize < 0)
4800 {
4801 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4802 return false;
4803 }
4804
4805 Program *programObject = GetValidProgram(context, program);
4806
4807 if (!programObject)
4808 {
4809 return false;
4810 }
4811
4812 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4813 {
4814 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4815 return false;
4816 }
4817
4818 return true;
4819 }
4820
ValidateGetAttachedShaders(const Context * context,ShaderProgramID program,GLsizei maxcount,const GLsizei * count,const ShaderProgramID * shaders)4821 bool ValidateGetAttachedShaders(const Context *context,
4822 ShaderProgramID program,
4823 GLsizei maxcount,
4824 const GLsizei *count,
4825 const ShaderProgramID *shaders)
4826 {
4827 if (maxcount < 0)
4828 {
4829 context->validationError(GL_INVALID_VALUE, kNegativeMaxCount);
4830 return false;
4831 }
4832
4833 Program *programObject = GetValidProgram(context, program);
4834
4835 if (!programObject)
4836 {
4837 return false;
4838 }
4839
4840 return true;
4841 }
4842
ValidateGetAttribLocation(const Context * context,ShaderProgramID program,const GLchar * name)4843 bool ValidateGetAttribLocation(const Context *context, ShaderProgramID program, const GLchar *name)
4844 {
4845 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4846 // shader-related entry points
4847 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4848 {
4849 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
4850 return false;
4851 }
4852
4853 Program *programObject = GetValidProgram(context, program);
4854
4855 if (!programObject)
4856 {
4857 context->validationError(GL_INVALID_OPERATION, kProgramNotBound);
4858 return false;
4859 }
4860
4861 if (!programObject->isLinked())
4862 {
4863 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4864 return false;
4865 }
4866
4867 return true;
4868 }
4869
ValidateGetBooleanv(const Context * context,GLenum pname,const GLboolean * params)4870 bool ValidateGetBooleanv(const Context *context, GLenum pname, const GLboolean *params)
4871 {
4872 GLenum nativeType;
4873 unsigned int numParams = 0;
4874 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4875 }
4876
ValidateGetError(const Context * context)4877 bool ValidateGetError(const Context *context)
4878 {
4879 return true;
4880 }
4881
ValidateGetFloatv(const Context * context,GLenum pname,const GLfloat * params)4882 bool ValidateGetFloatv(const Context *context, GLenum pname, const GLfloat *params)
4883 {
4884 GLenum nativeType;
4885 unsigned int numParams = 0;
4886 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4887 }
4888
ValidateGetIntegerv(const Context * context,GLenum pname,const GLint * params)4889 bool ValidateGetIntegerv(const Context *context, GLenum pname, const GLint *params)
4890 {
4891 GLenum nativeType;
4892 unsigned int numParams = 0;
4893 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4894 }
4895
ValidateGetProgramInfoLog(const Context * context,ShaderProgramID program,GLsizei bufsize,const GLsizei * length,const GLchar * infolog)4896 bool ValidateGetProgramInfoLog(const Context *context,
4897 ShaderProgramID program,
4898 GLsizei bufsize,
4899 const GLsizei *length,
4900 const GLchar *infolog)
4901 {
4902 if (bufsize < 0)
4903 {
4904 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4905 return false;
4906 }
4907
4908 Program *programObject = GetValidProgram(context, program);
4909 if (!programObject)
4910 {
4911 return false;
4912 }
4913
4914 return true;
4915 }
4916
ValidateGetShaderInfoLog(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * infolog)4917 bool ValidateGetShaderInfoLog(const Context *context,
4918 ShaderProgramID shader,
4919 GLsizei bufsize,
4920 const GLsizei *length,
4921 const GLchar *infolog)
4922 {
4923 if (bufsize < 0)
4924 {
4925 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4926 return false;
4927 }
4928
4929 Shader *shaderObject = GetValidShader(context, shader);
4930 if (!shaderObject)
4931 {
4932 return false;
4933 }
4934
4935 return true;
4936 }
4937
ValidateGetShaderPrecisionFormat(const Context * context,GLenum shadertype,GLenum precisiontype,const GLint * range,const GLint * precision)4938 bool ValidateGetShaderPrecisionFormat(const Context *context,
4939 GLenum shadertype,
4940 GLenum precisiontype,
4941 const GLint *range,
4942 const GLint *precision)
4943 {
4944 switch (shadertype)
4945 {
4946 case GL_VERTEX_SHADER:
4947 case GL_FRAGMENT_SHADER:
4948 break;
4949 case GL_COMPUTE_SHADER:
4950 context->validationError(GL_INVALID_OPERATION, kUnimplementedComputeShaderPrecision);
4951 return false;
4952 default:
4953 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
4954 return false;
4955 }
4956
4957 switch (precisiontype)
4958 {
4959 case GL_LOW_FLOAT:
4960 case GL_MEDIUM_FLOAT:
4961 case GL_HIGH_FLOAT:
4962 case GL_LOW_INT:
4963 case GL_MEDIUM_INT:
4964 case GL_HIGH_INT:
4965 break;
4966
4967 default:
4968 context->validationError(GL_INVALID_ENUM, kInvalidPrecision);
4969 return false;
4970 }
4971
4972 return true;
4973 }
4974
ValidateGetShaderSource(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * source)4975 bool ValidateGetShaderSource(const Context *context,
4976 ShaderProgramID shader,
4977 GLsizei bufsize,
4978 const GLsizei *length,
4979 const GLchar *source)
4980 {
4981 if (bufsize < 0)
4982 {
4983 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4984 return false;
4985 }
4986
4987 Shader *shaderObject = GetValidShader(context, shader);
4988 if (!shaderObject)
4989 {
4990 return false;
4991 }
4992
4993 return true;
4994 }
4995
ValidateGetUniformLocation(const Context * context,ShaderProgramID program,const GLchar * name)4996 bool ValidateGetUniformLocation(const Context *context, ShaderProgramID program, const GLchar *name)
4997 {
4998 if (strstr(name, "gl_") == name)
4999 {
5000 return false;
5001 }
5002
5003 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5004 // shader-related entry points
5005 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
5006 {
5007 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
5008 return false;
5009 }
5010
5011 Program *programObject = GetValidProgram(context, program);
5012
5013 if (!programObject)
5014 {
5015 return false;
5016 }
5017
5018 if (!programObject->isLinked())
5019 {
5020 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
5021 return false;
5022 }
5023
5024 return true;
5025 }
5026
ValidateHint(const Context * context,GLenum target,GLenum mode)5027 bool ValidateHint(const Context *context, GLenum target, GLenum mode)
5028 {
5029 switch (mode)
5030 {
5031 case GL_FASTEST:
5032 case GL_NICEST:
5033 case GL_DONT_CARE:
5034 break;
5035
5036 default:
5037 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5038 return false;
5039 }
5040
5041 switch (target)
5042 {
5043 case GL_GENERATE_MIPMAP_HINT:
5044 break;
5045
5046 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5047 if (context->getClientVersion() < ES_3_0 &&
5048 !context->getExtensions().standardDerivativesOES)
5049 {
5050 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5051 return false;
5052 }
5053 break;
5054
5055 case GL_PERSPECTIVE_CORRECTION_HINT:
5056 case GL_POINT_SMOOTH_HINT:
5057 case GL_LINE_SMOOTH_HINT:
5058 case GL_FOG_HINT:
5059 if (context->getClientMajorVersion() >= 2)
5060 {
5061 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5062 return false;
5063 }
5064 break;
5065
5066 default:
5067 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5068 return false;
5069 }
5070
5071 return true;
5072 }
5073
ValidateIsBuffer(const Context * context,BufferID buffer)5074 bool ValidateIsBuffer(const Context *context, BufferID buffer)
5075 {
5076 return true;
5077 }
5078
ValidateIsFramebuffer(const Context * context,FramebufferID framebuffer)5079 bool ValidateIsFramebuffer(const Context *context, FramebufferID framebuffer)
5080 {
5081 return true;
5082 }
5083
ValidateIsProgram(const Context * context,ShaderProgramID program)5084 bool ValidateIsProgram(const Context *context, ShaderProgramID program)
5085 {
5086 return true;
5087 }
5088
ValidateIsRenderbuffer(const Context * context,RenderbufferID renderbuffer)5089 bool ValidateIsRenderbuffer(const Context *context, RenderbufferID renderbuffer)
5090 {
5091 return true;
5092 }
5093
ValidateIsShader(const Context * context,ShaderProgramID shader)5094 bool ValidateIsShader(const Context *context, ShaderProgramID shader)
5095 {
5096 return true;
5097 }
5098
ValidateIsTexture(const Context * context,TextureID texture)5099 bool ValidateIsTexture(const Context *context, TextureID texture)
5100 {
5101 return true;
5102 }
5103
ValidatePixelStorei(const Context * context,GLenum pname,GLint param)5104 bool ValidatePixelStorei(const Context *context, GLenum pname, GLint param)
5105 {
5106 if (context->getClientMajorVersion() < 3)
5107 {
5108 switch (pname)
5109 {
5110 case GL_UNPACK_IMAGE_HEIGHT:
5111 case GL_UNPACK_SKIP_IMAGES:
5112 context->validationError(GL_INVALID_ENUM, kInvalidPname);
5113 return false;
5114
5115 case GL_UNPACK_ROW_LENGTH:
5116 case GL_UNPACK_SKIP_ROWS:
5117 case GL_UNPACK_SKIP_PIXELS:
5118 if (!context->getExtensions().unpackSubimage)
5119 {
5120 context->validationError(GL_INVALID_ENUM, kInvalidPname);
5121 return false;
5122 }
5123 break;
5124
5125 case GL_PACK_ROW_LENGTH:
5126 case GL_PACK_SKIP_ROWS:
5127 case GL_PACK_SKIP_PIXELS:
5128 if (!context->getExtensions().packSubimage)
5129 {
5130 context->validationError(GL_INVALID_ENUM, kInvalidPname);
5131 return false;
5132 }
5133 break;
5134 }
5135 }
5136
5137 if (param < 0)
5138 {
5139 context->validationError(GL_INVALID_VALUE, kNegativeParam);
5140 return false;
5141 }
5142
5143 switch (pname)
5144 {
5145 case GL_UNPACK_ALIGNMENT:
5146 if (param != 1 && param != 2 && param != 4 && param != 8)
5147 {
5148 context->validationError(GL_INVALID_VALUE, kInvalidUnpackAlignment);
5149 return false;
5150 }
5151 break;
5152
5153 case GL_PACK_ALIGNMENT:
5154 if (param != 1 && param != 2 && param != 4 && param != 8)
5155 {
5156 context->validationError(GL_INVALID_VALUE, kInvalidUnpackAlignment);
5157 return false;
5158 }
5159 break;
5160
5161 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5162 if (!context->getExtensions().packReverseRowOrder)
5163 {
5164 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5165 }
5166 break;
5167
5168 case GL_UNPACK_ROW_LENGTH:
5169 case GL_UNPACK_IMAGE_HEIGHT:
5170 case GL_UNPACK_SKIP_IMAGES:
5171 case GL_UNPACK_SKIP_ROWS:
5172 case GL_UNPACK_SKIP_PIXELS:
5173 case GL_PACK_ROW_LENGTH:
5174 case GL_PACK_SKIP_ROWS:
5175 case GL_PACK_SKIP_PIXELS:
5176 break;
5177
5178 default:
5179 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5180 return false;
5181 }
5182
5183 return true;
5184 }
5185
ValidatePolygonOffset(const Context * context,GLfloat factor,GLfloat units)5186 bool ValidatePolygonOffset(const Context *context, GLfloat factor, GLfloat units)
5187 {
5188 return true;
5189 }
5190
ValidateReleaseShaderCompiler(const Context * context)5191 bool ValidateReleaseShaderCompiler(const Context *context)
5192 {
5193 return true;
5194 }
5195
ValidateSampleCoverage(const Context * context,GLfloat value,GLboolean invert)5196 bool ValidateSampleCoverage(const Context *context, GLfloat value, GLboolean invert)
5197 {
5198 return true;
5199 }
5200
ValidateScissor(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height)5201 bool ValidateScissor(const Context *context, GLint x, GLint y, GLsizei width, GLsizei height)
5202 {
5203 if (width < 0 || height < 0)
5204 {
5205 context->validationError(GL_INVALID_VALUE, kNegativeSize);
5206 return false;
5207 }
5208
5209 return true;
5210 }
5211
ValidateShaderBinary(const Context * context,GLsizei n,const ShaderProgramID * shaders,GLenum binaryformat,const void * binary,GLsizei length)5212 bool ValidateShaderBinary(const Context *context,
5213 GLsizei n,
5214 const ShaderProgramID *shaders,
5215 GLenum binaryformat,
5216 const void *binary,
5217 GLsizei length)
5218 {
5219 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5220 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5221 shaderBinaryFormats.end())
5222 {
5223 context->validationError(GL_INVALID_ENUM, kInvalidShaderBinaryFormat);
5224 return false;
5225 }
5226
5227 return true;
5228 }
5229
ValidateShaderSource(const Context * context,ShaderProgramID shader,GLsizei count,const GLchar * const * string,const GLint * length)5230 bool ValidateShaderSource(const Context *context,
5231 ShaderProgramID shader,
5232 GLsizei count,
5233 const GLchar *const *string,
5234 const GLint *length)
5235 {
5236 if (count < 0)
5237 {
5238 context->validationError(GL_INVALID_VALUE, kNegativeCount);
5239 return false;
5240 }
5241
5242 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5243 // shader-related entry points
5244 if (context->getExtensions().webglCompatibility)
5245 {
5246 for (GLsizei i = 0; i < count; i++)
5247 {
5248 size_t len =
5249 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
5250
5251 // Backslash as line-continuation is allowed in WebGL 2.0.
5252 if (!IsValidESSLShaderSourceString(string[i], len,
5253 context->getClientVersion() >= ES_3_0))
5254 {
5255 context->validationError(GL_INVALID_VALUE, kShaderSourceInvalidCharacters);
5256 return false;
5257 }
5258 }
5259 }
5260
5261 Shader *shaderObject = GetValidShader(context, shader);
5262 if (!shaderObject)
5263 {
5264 return false;
5265 }
5266
5267 return true;
5268 }
5269
ValidateStencilFunc(const Context * context,GLenum func,GLint ref,GLuint mask)5270 bool ValidateStencilFunc(const Context *context, GLenum func, GLint ref, GLuint mask)
5271 {
5272 if (!IsValidStencilFunc(func))
5273 {
5274 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5275 return false;
5276 }
5277
5278 return true;
5279 }
5280
ValidateStencilFuncSeparate(const Context * context,GLenum face,GLenum func,GLint ref,GLuint mask)5281 bool ValidateStencilFuncSeparate(const Context *context,
5282 GLenum face,
5283 GLenum func,
5284 GLint ref,
5285 GLuint mask)
5286 {
5287 if (!IsValidStencilFace(face))
5288 {
5289 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5290 return false;
5291 }
5292
5293 if (!IsValidStencilFunc(func))
5294 {
5295 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5296 return false;
5297 }
5298
5299 return true;
5300 }
5301
ValidateStencilMask(const Context * context,GLuint mask)5302 bool ValidateStencilMask(const Context *context, GLuint mask)
5303 {
5304 return true;
5305 }
5306
ValidateStencilMaskSeparate(const Context * context,GLenum face,GLuint mask)5307 bool ValidateStencilMaskSeparate(const Context *context, GLenum face, GLuint mask)
5308 {
5309 if (!IsValidStencilFace(face))
5310 {
5311 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5312 return false;
5313 }
5314
5315 return true;
5316 }
5317
ValidateStencilOp(const Context * context,GLenum fail,GLenum zfail,GLenum zpass)5318 bool ValidateStencilOp(const Context *context, GLenum fail, GLenum zfail, GLenum zpass)
5319 {
5320 if (!IsValidStencilOp(fail))
5321 {
5322 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5323 return false;
5324 }
5325
5326 if (!IsValidStencilOp(zfail))
5327 {
5328 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5329 return false;
5330 }
5331
5332 if (!IsValidStencilOp(zpass))
5333 {
5334 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5335 return false;
5336 }
5337
5338 return true;
5339 }
5340
ValidateStencilOpSeparate(const Context * context,GLenum face,GLenum fail,GLenum zfail,GLenum zpass)5341 bool ValidateStencilOpSeparate(const Context *context,
5342 GLenum face,
5343 GLenum fail,
5344 GLenum zfail,
5345 GLenum zpass)
5346 {
5347 if (!IsValidStencilFace(face))
5348 {
5349 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
5350 return false;
5351 }
5352
5353 return ValidateStencilOp(context, fail, zfail, zpass);
5354 }
5355
ValidateUniform1f(const Context * context,UniformLocation location,GLfloat x)5356 bool ValidateUniform1f(const Context *context, UniformLocation location, GLfloat x)
5357 {
5358 return ValidateUniform(context, GL_FLOAT, location, 1);
5359 }
5360
ValidateUniform1fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)5361 bool ValidateUniform1fv(const Context *context,
5362 UniformLocation location,
5363 GLsizei count,
5364 const GLfloat *v)
5365 {
5366 return ValidateUniform(context, GL_FLOAT, location, count);
5367 }
5368
ValidateUniform1i(const Context * context,UniformLocation location,GLint x)5369 bool ValidateUniform1i(const Context *context, UniformLocation location, GLint x)
5370 {
5371 return ValidateUniform1iv(context, location, 1, &x);
5372 }
5373
ValidateUniform2fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)5374 bool ValidateUniform2fv(const Context *context,
5375 UniformLocation location,
5376 GLsizei count,
5377 const GLfloat *v)
5378 {
5379 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5380 }
5381
ValidateUniform2i(const Context * context,UniformLocation location,GLint x,GLint y)5382 bool ValidateUniform2i(const Context *context, UniformLocation location, GLint x, GLint y)
5383 {
5384 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5385 }
5386
ValidateUniform2iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)5387 bool ValidateUniform2iv(const Context *context,
5388 UniformLocation location,
5389 GLsizei count,
5390 const GLint *v)
5391 {
5392 return ValidateUniform(context, GL_INT_VEC2, location, count);
5393 }
5394
ValidateUniform3f(const Context * context,UniformLocation location,GLfloat x,GLfloat y,GLfloat z)5395 bool ValidateUniform3f(const Context *context,
5396 UniformLocation location,
5397 GLfloat x,
5398 GLfloat y,
5399 GLfloat z)
5400 {
5401 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5402 }
5403
ValidateUniform3fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)5404 bool ValidateUniform3fv(const Context *context,
5405 UniformLocation location,
5406 GLsizei count,
5407 const GLfloat *v)
5408 {
5409 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5410 }
5411
ValidateUniform3i(const Context * context,UniformLocation location,GLint x,GLint y,GLint z)5412 bool ValidateUniform3i(const Context *context, UniformLocation location, GLint x, GLint y, GLint z)
5413 {
5414 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5415 }
5416
ValidateUniform3iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)5417 bool ValidateUniform3iv(const Context *context,
5418 UniformLocation location,
5419 GLsizei count,
5420 const GLint *v)
5421 {
5422 return ValidateUniform(context, GL_INT_VEC3, location, count);
5423 }
5424
ValidateUniform4f(const Context * context,UniformLocation location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)5425 bool ValidateUniform4f(const Context *context,
5426 UniformLocation location,
5427 GLfloat x,
5428 GLfloat y,
5429 GLfloat z,
5430 GLfloat w)
5431 {
5432 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5433 }
5434
ValidateUniform4fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)5435 bool ValidateUniform4fv(const Context *context,
5436 UniformLocation location,
5437 GLsizei count,
5438 const GLfloat *v)
5439 {
5440 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5441 }
5442
ValidateUniform4i(const Context * context,UniformLocation location,GLint x,GLint y,GLint z,GLint w)5443 bool ValidateUniform4i(const Context *context,
5444 UniformLocation location,
5445 GLint x,
5446 GLint y,
5447 GLint z,
5448 GLint w)
5449 {
5450 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5451 }
5452
ValidateUniform4iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)5453 bool ValidateUniform4iv(const Context *context,
5454 UniformLocation location,
5455 GLsizei count,
5456 const GLint *v)
5457 {
5458 return ValidateUniform(context, GL_INT_VEC4, location, count);
5459 }
5460
ValidateUniformMatrix2fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)5461 bool ValidateUniformMatrix2fv(const Context *context,
5462 UniformLocation location,
5463 GLsizei count,
5464 GLboolean transpose,
5465 const GLfloat *value)
5466 {
5467 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5468 }
5469
ValidateUniformMatrix3fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)5470 bool ValidateUniformMatrix3fv(const Context *context,
5471 UniformLocation location,
5472 GLsizei count,
5473 GLboolean transpose,
5474 const GLfloat *value)
5475 {
5476 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5477 }
5478
ValidateUniformMatrix4fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)5479 bool ValidateUniformMatrix4fv(const Context *context,
5480 UniformLocation location,
5481 GLsizei count,
5482 GLboolean transpose,
5483 const GLfloat *value)
5484 {
5485 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5486 }
5487
ValidateValidateProgram(const Context * context,ShaderProgramID program)5488 bool ValidateValidateProgram(const Context *context, ShaderProgramID program)
5489 {
5490 Program *programObject = GetValidProgram(context, program);
5491
5492 if (!programObject)
5493 {
5494 return false;
5495 }
5496
5497 return true;
5498 }
5499
ValidateVertexAttrib1f(const Context * context,GLuint index,GLfloat x)5500 bool ValidateVertexAttrib1f(const Context *context, GLuint index, GLfloat x)
5501 {
5502 return ValidateVertexAttribIndex(context, index);
5503 }
5504
ValidateVertexAttrib1fv(const Context * context,GLuint index,const GLfloat * values)5505 bool ValidateVertexAttrib1fv(const Context *context, GLuint index, const GLfloat *values)
5506 {
5507 return ValidateVertexAttribIndex(context, index);
5508 }
5509
ValidateVertexAttrib2f(const Context * context,GLuint index,GLfloat x,GLfloat y)5510 bool ValidateVertexAttrib2f(const Context *context, GLuint index, GLfloat x, GLfloat y)
5511 {
5512 return ValidateVertexAttribIndex(context, index);
5513 }
5514
ValidateVertexAttrib2fv(const Context * context,GLuint index,const GLfloat * values)5515 bool ValidateVertexAttrib2fv(const Context *context, GLuint index, const GLfloat *values)
5516 {
5517 return ValidateVertexAttribIndex(context, index);
5518 }
5519
ValidateVertexAttrib3f(const Context * context,GLuint index,GLfloat x,GLfloat y,GLfloat z)5520 bool ValidateVertexAttrib3f(const Context *context, GLuint index, GLfloat x, GLfloat y, GLfloat z)
5521 {
5522 return ValidateVertexAttribIndex(context, index);
5523 }
5524
ValidateVertexAttrib3fv(const Context * context,GLuint index,const GLfloat * values)5525 bool ValidateVertexAttrib3fv(const Context *context, GLuint index, const GLfloat *values)
5526 {
5527 return ValidateVertexAttribIndex(context, index);
5528 }
5529
ValidateVertexAttrib4f(const Context * context,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)5530 bool ValidateVertexAttrib4f(const Context *context,
5531 GLuint index,
5532 GLfloat x,
5533 GLfloat y,
5534 GLfloat z,
5535 GLfloat w)
5536 {
5537 return ValidateVertexAttribIndex(context, index);
5538 }
5539
ValidateVertexAttrib4fv(const Context * context,GLuint index,const GLfloat * values)5540 bool ValidateVertexAttrib4fv(const Context *context, GLuint index, const GLfloat *values)
5541 {
5542 return ValidateVertexAttribIndex(context, index);
5543 }
5544
ValidateViewport(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height)5545 bool ValidateViewport(const Context *context, GLint x, GLint y, GLsizei width, GLsizei height)
5546 {
5547 if (width < 0 || height < 0)
5548 {
5549 context->validationError(GL_INVALID_VALUE, kViewportNegativeSize);
5550 return false;
5551 }
5552
5553 return true;
5554 }
5555
ValidateGetFramebufferAttachmentParameteriv(const Context * context,GLenum target,GLenum attachment,GLenum pname,const GLint * params)5556 bool ValidateGetFramebufferAttachmentParameteriv(const Context *context,
5557 GLenum target,
5558 GLenum attachment,
5559 GLenum pname,
5560 const GLint *params)
5561 {
5562 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5563 nullptr);
5564 }
5565
ValidateGetProgramiv(const Context * context,ShaderProgramID program,GLenum pname,const GLint * params)5566 bool ValidateGetProgramiv(const Context *context,
5567 ShaderProgramID program,
5568 GLenum pname,
5569 const GLint *params)
5570 {
5571 return ValidateGetProgramivBase(context, program, pname, nullptr);
5572 }
5573
ValidateCopyTexImage2D(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)5574 bool ValidateCopyTexImage2D(const Context *context,
5575 TextureTarget target,
5576 GLint level,
5577 GLenum internalformat,
5578 GLint x,
5579 GLint y,
5580 GLsizei width,
5581 GLsizei height,
5582 GLint border)
5583 {
5584 if (context->getClientMajorVersion() < 3)
5585 {
5586 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5587 0, x, y, width, height, border);
5588 }
5589
5590 ASSERT(context->getClientMajorVersion() == 3);
5591 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5592 0, x, y, width, height, border);
5593 }
5594
ValidateCopyTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)5595 bool ValidateCopyTexSubImage2D(const Context *context,
5596 TextureTarget target,
5597 GLint level,
5598 GLint xoffset,
5599 GLint yoffset,
5600 GLint x,
5601 GLint y,
5602 GLsizei width,
5603 GLsizei height)
5604 {
5605 if (context->getClientMajorVersion() < 3)
5606 {
5607 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5608 yoffset, x, y, width, height, 0);
5609 }
5610
5611 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5612 yoffset, 0, x, y, width, height, 0);
5613 }
5614
ValidateCopyTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)5615 bool ValidateCopyTexSubImage3DOES(const Context *context,
5616 TextureTarget target,
5617 GLint level,
5618 GLint xoffset,
5619 GLint yoffset,
5620 GLint zoffset,
5621 GLint x,
5622 GLint y,
5623 GLsizei width,
5624 GLsizei height)
5625 {
5626 return ValidateCopyTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, x, y, width,
5627 height);
5628 }
5629
ValidateDeleteBuffers(const Context * context,GLint n,const BufferID * buffers)5630 bool ValidateDeleteBuffers(const Context *context, GLint n, const BufferID *buffers)
5631 {
5632 return ValidateGenOrDelete(context, n);
5633 }
5634
ValidateDeleteFramebuffers(const Context * context,GLint n,const FramebufferID * framebuffers)5635 bool ValidateDeleteFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers)
5636 {
5637 return ValidateGenOrDelete(context, n);
5638 }
5639
ValidateDeleteRenderbuffers(const Context * context,GLint n,const RenderbufferID * renderbuffers)5640 bool ValidateDeleteRenderbuffers(const Context *context,
5641 GLint n,
5642 const RenderbufferID *renderbuffers)
5643 {
5644 return ValidateGenOrDelete(context, n);
5645 }
5646
ValidateDeleteTextures(const Context * context,GLint n,const TextureID * textures)5647 bool ValidateDeleteTextures(const Context *context, GLint n, const TextureID *textures)
5648 {
5649 return ValidateGenOrDelete(context, n);
5650 }
5651
ValidateDisable(const Context * context,GLenum cap)5652 bool ValidateDisable(const Context *context, GLenum cap)
5653 {
5654 if (!ValidCap(context, cap, false))
5655 {
5656 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5657 return false;
5658 }
5659
5660 return true;
5661 }
5662
ValidateEnable(const Context * context,GLenum cap)5663 bool ValidateEnable(const Context *context, GLenum cap)
5664 {
5665 if (!ValidCap(context, cap, false))
5666 {
5667 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5668 return false;
5669 }
5670
5671 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5672 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5673 {
5674 context->validationError(GL_INVALID_OPERATION, kNoSampleAlphaToCoveragesLimitation);
5675
5676 // We also output an error message to the debugger window if tracing is active, so that
5677 // developers can see the error message.
5678 ERR() << kNoSampleAlphaToCoveragesLimitation;
5679 return false;
5680 }
5681
5682 return true;
5683 }
5684
ValidateFramebufferRenderbuffer(const Context * context,GLenum target,GLenum attachment,GLenum renderbuffertarget,RenderbufferID renderbuffer)5685 bool ValidateFramebufferRenderbuffer(const Context *context,
5686 GLenum target,
5687 GLenum attachment,
5688 GLenum renderbuffertarget,
5689 RenderbufferID renderbuffer)
5690 {
5691 if (!ValidFramebufferTarget(context, target))
5692 {
5693 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
5694 return false;
5695 }
5696
5697 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer.value != 0)
5698 {
5699 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
5700 return false;
5701 }
5702
5703 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5704 renderbuffertarget, renderbuffer);
5705 }
5706
ValidateFramebufferTexture2D(const Context * context,GLenum target,GLenum attachment,TextureTarget textarget,TextureID texture,GLint level)5707 bool ValidateFramebufferTexture2D(const Context *context,
5708 GLenum target,
5709 GLenum attachment,
5710 TextureTarget textarget,
5711 TextureID texture,
5712 GLint level)
5713 {
5714 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5715 // extension
5716 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
5717 level != 0)
5718 {
5719 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
5720 return false;
5721 }
5722
5723 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5724 {
5725 return false;
5726 }
5727
5728 if (texture.value != 0)
5729 {
5730 Texture *tex = context->getTexture(texture);
5731 ASSERT(tex);
5732
5733 const Caps &caps = context->getCaps();
5734
5735 switch (textarget)
5736 {
5737 case TextureTarget::_2D:
5738 {
5739 if (level > log2(caps.max2DTextureSize))
5740 {
5741 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5742 return false;
5743 }
5744 if (tex->getType() != TextureType::_2D)
5745 {
5746 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
5747 return false;
5748 }
5749 }
5750 break;
5751
5752 case TextureTarget::Rectangle:
5753 {
5754 if (level != 0)
5755 {
5756 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5757 return false;
5758 }
5759 if (tex->getType() != TextureType::Rectangle)
5760 {
5761 context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5762 return false;
5763 }
5764 }
5765 break;
5766
5767 case TextureTarget::CubeMapNegativeX:
5768 case TextureTarget::CubeMapNegativeY:
5769 case TextureTarget::CubeMapNegativeZ:
5770 case TextureTarget::CubeMapPositiveX:
5771 case TextureTarget::CubeMapPositiveY:
5772 case TextureTarget::CubeMapPositiveZ:
5773 {
5774 if (level > log2(caps.maxCubeMapTextureSize))
5775 {
5776 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5777 return false;
5778 }
5779 if (tex->getType() != TextureType::CubeMap)
5780 {
5781 context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5782 return false;
5783 }
5784 }
5785 break;
5786
5787 case TextureTarget::_2DMultisample:
5788 {
5789 if (context->getClientVersion() < ES_3_1 &&
5790 !context->getExtensions().textureMultisample)
5791 {
5792 context->validationError(GL_INVALID_OPERATION,
5793 kMultisampleTextureExtensionOrES31Required);
5794 return false;
5795 }
5796
5797 if (level != 0)
5798 {
5799 context->validationError(GL_INVALID_VALUE, kLevelNotZero);
5800 return false;
5801 }
5802 if (tex->getType() != TextureType::_2DMultisample)
5803 {
5804 context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5805 return false;
5806 }
5807 }
5808 break;
5809
5810 default:
5811 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5812 return false;
5813 }
5814 }
5815
5816 return true;
5817 }
5818
ValidateFramebufferTexture3DOES(const Context * context,GLenum target,GLenum attachment,TextureTarget textargetPacked,TextureID texture,GLint level,GLint zoffset)5819 bool ValidateFramebufferTexture3DOES(const Context *context,
5820 GLenum target,
5821 GLenum attachment,
5822 TextureTarget textargetPacked,
5823 TextureID texture,
5824 GLint level,
5825 GLint zoffset)
5826 {
5827 // We don't call into a base ValidateFramebufferTexture3D here because
5828 // it doesn't exist for OpenGL ES. This function is replaced by
5829 // FramebufferTextureLayer in ES 3.x, which has broader support.
5830 if (!context->getExtensions().texture3DOES)
5831 {
5832 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5833 return false;
5834 }
5835
5836 // Attachments are required to be bound to level 0 without ES3 or the
5837 // GL_OES_fbo_render_mipmap extension
5838 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
5839 level != 0)
5840 {
5841 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
5842 return false;
5843 }
5844
5845 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5846 {
5847 return false;
5848 }
5849
5850 if (texture.value != 0)
5851 {
5852 Texture *tex = context->getTexture(texture);
5853 ASSERT(tex);
5854
5855 const Caps &caps = context->getCaps();
5856
5857 switch (textargetPacked)
5858 {
5859 case TextureTarget::_3D:
5860 {
5861 if (level > log2(caps.max3DTextureSize))
5862 {
5863 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5864 return false;
5865 }
5866 if (zoffset >= caps.max3DTextureSize)
5867 {
5868 context->validationError(GL_INVALID_VALUE, kInvalidZOffset);
5869 return false;
5870 }
5871 if (tex->getType() != TextureType::_3D)
5872 {
5873 context->validationError(GL_INVALID_OPERATION, kInvalidTextureType);
5874 return false;
5875 }
5876 }
5877 break;
5878
5879 default:
5880 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
5881 return false;
5882 }
5883 }
5884
5885 return true;
5886 }
5887
ValidateGenBuffers(const Context * context,GLint n,const BufferID * buffers)5888 bool ValidateGenBuffers(const Context *context, GLint n, const BufferID *buffers)
5889 {
5890 return ValidateGenOrDelete(context, n);
5891 }
5892
ValidateGenFramebuffers(const Context * context,GLint n,const FramebufferID * framebuffers)5893 bool ValidateGenFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers)
5894 {
5895 return ValidateGenOrDelete(context, n);
5896 }
5897
ValidateGenRenderbuffers(const Context * context,GLint n,const RenderbufferID * renderbuffers)5898 bool ValidateGenRenderbuffers(const Context *context, GLint n, const RenderbufferID *renderbuffers)
5899 {
5900 return ValidateGenOrDelete(context, n);
5901 }
5902
ValidateGenTextures(const Context * context,GLint n,const TextureID * textures)5903 bool ValidateGenTextures(const Context *context, GLint n, const TextureID *textures)
5904 {
5905 return ValidateGenOrDelete(context, n);
5906 }
5907
ValidateGenerateMipmap(const Context * context,TextureType target)5908 bool ValidateGenerateMipmap(const Context *context, TextureType target)
5909 {
5910 if (!ValidTextureTarget(context, target))
5911 {
5912 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5913 return false;
5914 }
5915
5916 Texture *texture = context->getTextureByType(target);
5917
5918 if (texture == nullptr)
5919 {
5920 context->validationError(GL_INVALID_OPERATION, kTextureNotBound);
5921 return false;
5922 }
5923
5924 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5925
5926 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5927 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5928 if (effectiveBaseLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5929 {
5930 context->validationError(GL_INVALID_OPERATION, kBaseLevelOutOfRange);
5931 return false;
5932 }
5933
5934 TextureTarget baseTarget = (target == TextureType::CubeMap)
5935 ? TextureTarget::CubeMapPositiveX
5936 : NonCubeTextureTypeToTarget(target);
5937 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
5938 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
5939 format.stencilBits > 0)
5940 {
5941 context->validationError(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
5942 return false;
5943 }
5944
5945 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
5946 bool formatUnsized = !format.sized;
5947 bool formatColorRenderableAndFilterable =
5948 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
5949 format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
5950 if (!formatUnsized && !formatColorRenderableAndFilterable)
5951 {
5952 context->validationError(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
5953 return false;
5954 }
5955
5956 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
5957 // generation
5958 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
5959 {
5960 context->validationError(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
5961 return false;
5962 }
5963
5964 // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on ES 2.0 and
5965 // generateMipmap is not allowed if texture format is SRGB_EXT or SRGB_ALPHA_EXT.
5966 if (context->getClientVersion() < Version(3, 0) && format.colorEncoding == GL_SRGB)
5967 {
5968 context->validationError(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
5969 return false;
5970 }
5971
5972 // Non-power of 2 ES2 check
5973 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOTOES &&
5974 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5975 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5976 {
5977 ASSERT(target == TextureType::_2D || target == TextureType::Rectangle ||
5978 target == TextureType::CubeMap);
5979 context->validationError(GL_INVALID_OPERATION, kTextureNotPow2);
5980 return false;
5981 }
5982
5983 // Cube completeness check
5984 if (target == TextureType::CubeMap && !texture->getTextureState().isCubeComplete())
5985 {
5986 context->validationError(GL_INVALID_OPERATION, kCubemapIncomplete);
5987 return false;
5988 }
5989
5990 if (context->getExtensions().webglCompatibility &&
5991 (texture->getWidth(baseTarget, effectiveBaseLevel) == 0 ||
5992 texture->getHeight(baseTarget, effectiveBaseLevel) == 0))
5993 {
5994 context->validationError(GL_INVALID_OPERATION, kGenerateMipmapZeroSize);
5995 return false;
5996 }
5997
5998 return true;
5999 }
6000
ValidateGetBufferParameteriv(const Context * context,BufferBinding target,GLenum pname,const GLint * params)6001 bool ValidateGetBufferParameteriv(const Context *context,
6002 BufferBinding target,
6003 GLenum pname,
6004 const GLint *params)
6005 {
6006 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6007 }
6008
ValidateGetRenderbufferParameteriv(const Context * context,GLenum target,GLenum pname,const GLint * params)6009 bool ValidateGetRenderbufferParameteriv(const Context *context,
6010 GLenum target,
6011 GLenum pname,
6012 const GLint *params)
6013 {
6014 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6015 }
6016
ValidateGetShaderiv(const Context * context,ShaderProgramID shader,GLenum pname,const GLint * params)6017 bool ValidateGetShaderiv(const Context *context,
6018 ShaderProgramID shader,
6019 GLenum pname,
6020 const GLint *params)
6021 {
6022 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6023 }
6024
ValidateGetTexParameterfv(const Context * context,TextureType target,GLenum pname,const GLfloat * params)6025 bool ValidateGetTexParameterfv(const Context *context,
6026 TextureType target,
6027 GLenum pname,
6028 const GLfloat *params)
6029 {
6030 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6031 }
6032
ValidateGetTexParameteriv(const Context * context,TextureType target,GLenum pname,const GLint * params)6033 bool ValidateGetTexParameteriv(const Context *context,
6034 TextureType target,
6035 GLenum pname,
6036 const GLint *params)
6037 {
6038 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6039 }
6040
ValidateGetTexParameterIivOES(const Context * context,TextureType target,GLenum pname,const GLint * params)6041 bool ValidateGetTexParameterIivOES(const Context *context,
6042 TextureType target,
6043 GLenum pname,
6044 const GLint *params)
6045 {
6046 if (context->getClientMajorVersion() < 3)
6047 {
6048 context->validationError(GL_INVALID_OPERATION, kES3Required);
6049 return false;
6050 }
6051 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6052 }
6053
ValidateGetTexParameterIuivOES(const Context * context,TextureType target,GLenum pname,const GLuint * params)6054 bool ValidateGetTexParameterIuivOES(const Context *context,
6055 TextureType target,
6056 GLenum pname,
6057 const GLuint *params)
6058 {
6059 if (context->getClientMajorVersion() < 3)
6060 {
6061 context->validationError(GL_INVALID_OPERATION, kES3Required);
6062 return false;
6063 }
6064 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6065 }
6066
ValidateGetUniformfv(const Context * context,ShaderProgramID program,UniformLocation location,const GLfloat * params)6067 bool ValidateGetUniformfv(const Context *context,
6068 ShaderProgramID program,
6069 UniformLocation location,
6070 const GLfloat *params)
6071 {
6072 return ValidateGetUniformBase(context, program, location);
6073 }
6074
ValidateGetUniformiv(const Context * context,ShaderProgramID program,UniformLocation location,const GLint * params)6075 bool ValidateGetUniformiv(const Context *context,
6076 ShaderProgramID program,
6077 UniformLocation location,
6078 const GLint *params)
6079 {
6080 return ValidateGetUniformBase(context, program, location);
6081 }
6082
ValidateGetVertexAttribfv(const Context * context,GLuint index,GLenum pname,const GLfloat * params)6083 bool ValidateGetVertexAttribfv(const Context *context,
6084 GLuint index,
6085 GLenum pname,
6086 const GLfloat *params)
6087 {
6088 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6089 }
6090
ValidateGetVertexAttribiv(const Context * context,GLuint index,GLenum pname,const GLint * params)6091 bool ValidateGetVertexAttribiv(const Context *context,
6092 GLuint index,
6093 GLenum pname,
6094 const GLint *params)
6095 {
6096 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6097 }
6098
ValidateGetVertexAttribPointerv(const Context * context,GLuint index,GLenum pname,void * const * pointer)6099 bool ValidateGetVertexAttribPointerv(const Context *context,
6100 GLuint index,
6101 GLenum pname,
6102 void *const *pointer)
6103 {
6104 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6105 }
6106
ValidateIsEnabled(const Context * context,GLenum cap)6107 bool ValidateIsEnabled(const Context *context, GLenum cap)
6108 {
6109 if (!ValidCap(context, cap, true))
6110 {
6111 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6112 return false;
6113 }
6114
6115 return true;
6116 }
6117
ValidateLinkProgram(const Context * context,ShaderProgramID program)6118 bool ValidateLinkProgram(const Context *context, ShaderProgramID program)
6119 {
6120 if (context->hasActiveTransformFeedback(program))
6121 {
6122 // ES 3.0.4 section 2.15 page 91
6123 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackActiveDuringLink);
6124 return false;
6125 }
6126
6127 Program *programObject = GetValidProgram(context, program);
6128 if (!programObject)
6129 {
6130 return false;
6131 }
6132
6133 return true;
6134 }
6135
ValidateReadPixels(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)6136 bool ValidateReadPixels(const Context *context,
6137 GLint x,
6138 GLint y,
6139 GLsizei width,
6140 GLsizei height,
6141 GLenum format,
6142 GLenum type,
6143 const void *pixels)
6144 {
6145 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6146 nullptr, pixels);
6147 }
6148
ValidateTexParameterf(const Context * context,TextureType target,GLenum pname,GLfloat param)6149 bool ValidateTexParameterf(const Context *context, TextureType target, GLenum pname, GLfloat param)
6150 {
6151 return ValidateTexParameterBase(context, target, pname, -1, false, ¶m);
6152 }
6153
ValidateTexParameterfv(const Context * context,TextureType target,GLenum pname,const GLfloat * params)6154 bool ValidateTexParameterfv(const Context *context,
6155 TextureType target,
6156 GLenum pname,
6157 const GLfloat *params)
6158 {
6159 return ValidateTexParameterBase(context, target, pname, -1, true, params);
6160 }
6161
ValidateTexParameteri(const Context * context,TextureType target,GLenum pname,GLint param)6162 bool ValidateTexParameteri(const Context *context, TextureType target, GLenum pname, GLint param)
6163 {
6164 return ValidateTexParameterBase(context, target, pname, -1, false, ¶m);
6165 }
6166
ValidateTexParameteriv(const Context * context,TextureType target,GLenum pname,const GLint * params)6167 bool ValidateTexParameteriv(const Context *context,
6168 TextureType target,
6169 GLenum pname,
6170 const GLint *params)
6171 {
6172 return ValidateTexParameterBase(context, target, pname, -1, true, params);
6173 }
6174
ValidateTexParameterIivOES(const Context * context,TextureType target,GLenum pname,const GLint * params)6175 bool ValidateTexParameterIivOES(const Context *context,
6176 TextureType target,
6177 GLenum pname,
6178 const GLint *params)
6179 {
6180 if (context->getClientMajorVersion() < 3)
6181 {
6182 context->validationError(GL_INVALID_OPERATION, kES3Required);
6183 return false;
6184 }
6185 return ValidateTexParameterBase(context, target, pname, -1, true, params);
6186 }
6187
ValidateTexParameterIuivOES(const Context * context,TextureType target,GLenum pname,const GLuint * params)6188 bool ValidateTexParameterIuivOES(const Context *context,
6189 TextureType target,
6190 GLenum pname,
6191 const GLuint *params)
6192 {
6193 if (context->getClientMajorVersion() < 3)
6194 {
6195 context->validationError(GL_INVALID_OPERATION, kES3Required);
6196 return false;
6197 }
6198 return ValidateTexParameterBase(context, target, pname, -1, true, params);
6199 }
6200
ValidateUseProgram(const Context * context,ShaderProgramID program)6201 bool ValidateUseProgram(const Context *context, ShaderProgramID program)
6202 {
6203 if (program.value != 0)
6204 {
6205 Program *programObject = context->getProgramResolveLink(program);
6206 if (!programObject)
6207 {
6208 // ES 3.1.0 section 7.3 page 72
6209 if (context->getShader(program))
6210 {
6211 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
6212 return false;
6213 }
6214 else
6215 {
6216 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
6217 return false;
6218 }
6219 }
6220 if (!programObject->isLinked())
6221 {
6222 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
6223 return false;
6224 }
6225 }
6226 if (context->getState().isTransformFeedbackActiveUnpaused())
6227 {
6228 // ES 3.0.4 section 2.15 page 91
6229 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackUseProgram);
6230 return false;
6231 }
6232
6233 return true;
6234 }
6235
ValidateDeleteFencesNV(const Context * context,GLsizei n,const FenceNVID * fences)6236 bool ValidateDeleteFencesNV(const Context *context, GLsizei n, const FenceNVID *fences)
6237 {
6238 if (!context->getExtensions().fenceNV)
6239 {
6240 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
6241 return false;
6242 }
6243
6244 if (n < 0)
6245 {
6246 context->validationError(GL_INVALID_VALUE, kNegativeCount);
6247 return false;
6248 }
6249
6250 return true;
6251 }
6252
ValidateFinishFenceNV(const Context * context,FenceNVID fence)6253 bool ValidateFinishFenceNV(const Context *context, FenceNVID fence)
6254 {
6255 if (!context->getExtensions().fenceNV)
6256 {
6257 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
6258 return false;
6259 }
6260
6261 FenceNV *fenceObject = context->getFenceNV(fence);
6262
6263 if (fenceObject == nullptr)
6264 {
6265 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
6266 return false;
6267 }
6268
6269 if (!fenceObject->isSet())
6270 {
6271 context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
6272 return false;
6273 }
6274
6275 return true;
6276 }
6277
ValidateGenFencesNV(const Context * context,GLsizei n,const FenceNVID * fences)6278 bool ValidateGenFencesNV(const Context *context, GLsizei n, const FenceNVID *fences)
6279 {
6280 if (!context->getExtensions().fenceNV)
6281 {
6282 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
6283 return false;
6284 }
6285
6286 if (n < 0)
6287 {
6288 context->validationError(GL_INVALID_VALUE, kNegativeCount);
6289 return false;
6290 }
6291
6292 return true;
6293 }
6294
ValidateGetFenceivNV(const Context * context,FenceNVID fence,GLenum pname,const GLint * params)6295 bool ValidateGetFenceivNV(const Context *context,
6296 FenceNVID fence,
6297 GLenum pname,
6298 const GLint *params)
6299 {
6300 if (!context->getExtensions().fenceNV)
6301 {
6302 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
6303 return false;
6304 }
6305
6306 FenceNV *fenceObject = context->getFenceNV(fence);
6307
6308 if (fenceObject == nullptr)
6309 {
6310 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
6311 return false;
6312 }
6313
6314 if (!fenceObject->isSet())
6315 {
6316 context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
6317 return false;
6318 }
6319
6320 switch (pname)
6321 {
6322 case GL_FENCE_STATUS_NV:
6323 case GL_FENCE_CONDITION_NV:
6324 break;
6325
6326 default:
6327 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6328 return false;
6329 }
6330
6331 return true;
6332 }
6333
ValidateGetGraphicsResetStatusEXT(const Context * context)6334 bool ValidateGetGraphicsResetStatusEXT(const Context *context)
6335 {
6336 if (!context->getExtensions().robustness)
6337 {
6338 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6339 return false;
6340 }
6341
6342 return true;
6343 }
6344
ValidateGetTranslatedShaderSourceANGLE(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * source)6345 bool ValidateGetTranslatedShaderSourceANGLE(const Context *context,
6346 ShaderProgramID shader,
6347 GLsizei bufsize,
6348 const GLsizei *length,
6349 const GLchar *source)
6350 {
6351 if (!context->getExtensions().translatedShaderSource)
6352 {
6353 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6354 return false;
6355 }
6356
6357 if (bufsize < 0)
6358 {
6359 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
6360 return false;
6361 }
6362
6363 Shader *shaderObject = context->getShader(shader);
6364
6365 if (!shaderObject)
6366 {
6367 context->validationError(GL_INVALID_OPERATION, kInvalidShaderName);
6368 return false;
6369 }
6370
6371 return true;
6372 }
6373
ValidateIsFenceNV(const Context * context,FenceNVID fence)6374 bool ValidateIsFenceNV(const Context *context, FenceNVID fence)
6375 {
6376 if (!context->getExtensions().fenceNV)
6377 {
6378 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
6379 return false;
6380 }
6381
6382 return true;
6383 }
6384
ValidateSetFenceNV(const Context * context,FenceNVID fence,GLenum condition)6385 bool ValidateSetFenceNV(const Context *context, FenceNVID fence, GLenum condition)
6386 {
6387 if (!context->getExtensions().fenceNV)
6388 {
6389 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
6390 return false;
6391 }
6392
6393 if (condition != GL_ALL_COMPLETED_NV)
6394 {
6395 context->validationError(GL_INVALID_ENUM, kInvalidFenceCondition);
6396 return false;
6397 }
6398
6399 FenceNV *fenceObject = context->getFenceNV(fence);
6400
6401 if (fenceObject == nullptr)
6402 {
6403 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
6404 return false;
6405 }
6406
6407 return true;
6408 }
6409
ValidateTestFenceNV(const Context * context,FenceNVID fence)6410 bool ValidateTestFenceNV(const Context *context, FenceNVID fence)
6411 {
6412 if (!context->getExtensions().fenceNV)
6413 {
6414 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
6415 return false;
6416 }
6417
6418 FenceNV *fenceObject = context->getFenceNV(fence);
6419
6420 if (fenceObject == nullptr)
6421 {
6422 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
6423 return false;
6424 }
6425
6426 if (fenceObject->isSet() != GL_TRUE)
6427 {
6428 context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
6429 return false;
6430 }
6431
6432 return true;
6433 }
6434
ValidateTexStorage2DEXT(const Context * context,TextureType type,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)6435 bool ValidateTexStorage2DEXT(const Context *context,
6436 TextureType type,
6437 GLsizei levels,
6438 GLenum internalformat,
6439 GLsizei width,
6440 GLsizei height)
6441 {
6442 if (!context->getExtensions().textureStorage)
6443 {
6444 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6445 return false;
6446 }
6447
6448 if (context->getClientMajorVersion() < 3)
6449 {
6450 return ValidateES2TexStorageParameters(context, type, levels, internalformat, width,
6451 height);
6452 }
6453
6454 ASSERT(context->getClientMajorVersion() >= 3);
6455 return ValidateES3TexStorage2DParameters(context, type, levels, internalformat, width, height,
6456 1);
6457 }
6458
ValidateVertexAttribDivisorANGLE(const Context * context,GLuint index,GLuint divisor)6459 bool ValidateVertexAttribDivisorANGLE(const Context *context, GLuint index, GLuint divisor)
6460 {
6461 if (!context->getExtensions().instancedArraysANGLE)
6462 {
6463 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6464 return false;
6465 }
6466
6467 if (index >= MAX_VERTEX_ATTRIBS)
6468 {
6469 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
6470 return false;
6471 }
6472
6473 if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT)
6474 {
6475 if (index == 0 && divisor != 0)
6476 {
6477 context->validationError(GL_INVALID_OPERATION, kAttributeZeroRequiresDivisorLimitation);
6478
6479 // We also output an error message to the debugger window if tracing is active, so
6480 // that developers can see the error message.
6481 ERR() << kAttributeZeroRequiresDivisorLimitation;
6482 return false;
6483 }
6484 }
6485
6486 return true;
6487 }
6488
ValidateVertexAttribDivisorEXT(const Context * context,GLuint index,GLuint divisor)6489 bool ValidateVertexAttribDivisorEXT(const Context *context, GLuint index, GLuint divisor)
6490 {
6491 if (!context->getExtensions().instancedArraysEXT)
6492 {
6493 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6494 return false;
6495 }
6496
6497 if (index >= MAX_VERTEX_ATTRIBS)
6498 {
6499 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
6500 return false;
6501 }
6502
6503 return true;
6504 }
6505
ValidateTexImage3DOES(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)6506 bool ValidateTexImage3DOES(const Context *context,
6507 TextureTarget target,
6508 GLint level,
6509 GLenum internalformat,
6510 GLsizei width,
6511 GLsizei height,
6512 GLsizei depth,
6513 GLint border,
6514 GLenum format,
6515 GLenum type,
6516 const void *pixels)
6517 {
6518 return ValidateTexImage3D(context, target, level, internalformat, width, height, depth, border,
6519 format, type, pixels);
6520 }
6521
ValidatePopGroupMarkerEXT(const Context * context)6522 bool ValidatePopGroupMarkerEXT(const Context *context)
6523 {
6524 if (!context->getExtensions().debugMarker)
6525 {
6526 // The debug marker calls should not set error state
6527 // However, it seems reasonable to set an error state if the extension is not enabled
6528 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6529 return false;
6530 }
6531
6532 return true;
6533 }
6534
ValidateTexStorage1DEXT(const Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)6535 bool ValidateTexStorage1DEXT(const Context *context,
6536 GLenum target,
6537 GLsizei levels,
6538 GLenum internalformat,
6539 GLsizei width)
6540 {
6541 UNIMPLEMENTED();
6542 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6543 return false;
6544 }
6545
ValidateTexStorage3DEXT(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)6546 bool ValidateTexStorage3DEXT(const Context *context,
6547 TextureType target,
6548 GLsizei levels,
6549 GLenum internalformat,
6550 GLsizei width,
6551 GLsizei height,
6552 GLsizei depth)
6553 {
6554 if (!context->getExtensions().textureStorage)
6555 {
6556 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6557 return false;
6558 }
6559
6560 if (context->getClientMajorVersion() < 3)
6561 {
6562 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6563 return false;
6564 }
6565
6566 return ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
6567 depth);
6568 }
6569
ValidateMaxShaderCompilerThreadsKHR(const Context * context,GLuint count)6570 bool ValidateMaxShaderCompilerThreadsKHR(const Context *context, GLuint count)
6571 {
6572 if (!context->getExtensions().parallelShaderCompile)
6573 {
6574 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6575 return false;
6576 }
6577 return true;
6578 }
6579
ValidateMultiDrawArraysANGLE(const Context * context,PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)6580 bool ValidateMultiDrawArraysANGLE(const Context *context,
6581 PrimitiveMode mode,
6582 const GLint *firsts,
6583 const GLsizei *counts,
6584 GLsizei drawcount)
6585 {
6586 if (!context->getExtensions().multiDraw)
6587 {
6588 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6589 return false;
6590 }
6591 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
6592 {
6593 if (!ValidateDrawArrays(context, mode, firsts[drawID], counts[drawID]))
6594 {
6595 return false;
6596 }
6597 }
6598 return true;
6599 }
6600
ValidateMultiDrawElementsANGLE(const Context * context,PrimitiveMode mode,const GLsizei * counts,DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)6601 bool ValidateMultiDrawElementsANGLE(const Context *context,
6602 PrimitiveMode mode,
6603 const GLsizei *counts,
6604 DrawElementsType type,
6605 const GLvoid *const *indices,
6606 GLsizei drawcount)
6607 {
6608 if (!context->getExtensions().multiDraw)
6609 {
6610 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6611 return false;
6612 }
6613 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
6614 {
6615 if (!ValidateDrawElements(context, mode, counts[drawID], type, indices[drawID]))
6616 {
6617 return false;
6618 }
6619 }
6620 return true;
6621 }
6622
ValidateProvokingVertexANGLE(const Context * context,ProvokingVertexConvention modePacked)6623 bool ValidateProvokingVertexANGLE(const Context *context, ProvokingVertexConvention modePacked)
6624 {
6625 if (!context->getExtensions().provokingVertex)
6626 {
6627 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6628 return false;
6629 }
6630
6631 switch (modePacked)
6632 {
6633 case ProvokingVertexConvention::FirstVertexConvention:
6634 case ProvokingVertexConvention::LastVertexConvention:
6635 break;
6636 default:
6637 context->validationError(GL_INVALID_ENUM, kInvalidProvokingVertex);
6638 return false;
6639 }
6640
6641 return true;
6642 }
6643
ValidateFramebufferTexture2DMultisampleEXT(const Context * context,GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLsizei samples)6644 bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context,
6645 GLenum target,
6646 GLenum attachment,
6647 GLenum textarget,
6648 GLuint texture,
6649 GLint level,
6650 GLsizei samples)
6651 {
6652 if (!context->getExtensions().multisampledRenderToTexture)
6653 {
6654 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6655 return false;
6656 }
6657
6658 if (samples < 0)
6659 {
6660 return false;
6661 }
6662
6663 // EXT_multisampled_render_to_texture states that the value of samples
6664 // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
6665 // otherwise GL_INVALID_VALUE is generated.
6666 if (samples > context->getCaps().maxSamples)
6667 {
6668 context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
6669 return false;
6670 }
6671
6672 if (!ValidFramebufferTarget(context, target))
6673 {
6674 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
6675 return false;
6676 }
6677
6678 if (attachment != GL_COLOR_ATTACHMENT0)
6679 {
6680 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
6681 return false;
6682 }
6683
6684 TextureTarget textargetPacked = FromGLenum<TextureTarget>(textarget);
6685 if (!ValidTexture2DDestinationTarget(context, textargetPacked))
6686 {
6687 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6688 return false;
6689 }
6690
6691 if (texture != 0)
6692 {
6693 TextureID texturePacked = FromGL<TextureID>(texture);
6694 Texture *tex = context->getTexture(texturePacked);
6695
6696 if (tex == nullptr)
6697 {
6698 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
6699 return false;
6700 }
6701
6702 if (level < 0)
6703 {
6704 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
6705 return false;
6706 }
6707
6708 // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher
6709 // than the maximum sample number supported by this format is passed.
6710 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is
6711 // ES3.
6712 if (context->getClientMajorVersion() >= 3)
6713 {
6714 GLenum internalformat = tex->getFormat(textargetPacked, level).info->internalFormat;
6715 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6716 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6717 {
6718 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
6719 return false;
6720 }
6721 }
6722 }
6723
6724 return true;
6725 }
6726
ValidateRenderbufferStorageMultisampleEXT(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)6727 bool ValidateRenderbufferStorageMultisampleEXT(const Context *context,
6728 GLenum target,
6729 GLsizei samples,
6730 GLenum internalformat,
6731 GLsizei width,
6732 GLsizei height)
6733 {
6734 if (!context->getExtensions().multisampledRenderToTexture)
6735 {
6736 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6737 return false;
6738 }
6739 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
6740 height))
6741 {
6742 return false;
6743 }
6744
6745 // EXT_multisampled_render_to_texture states that the value of samples
6746 // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
6747 // otherwise GL_INVALID_VALUE is generated.
6748 if (samples > context->getCaps().maxSamples)
6749 {
6750 context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
6751 return false;
6752 }
6753
6754 // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on failure to create
6755 // the specified storage. This is different than ES 3.0 in which a sample number higher
6756 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
6757 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
6758 if (context->getClientMajorVersion() >= 3)
6759 {
6760 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6761 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6762 {
6763 context->validationError(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
6764 return false;
6765 }
6766 }
6767
6768 return true;
6769 }
6770
RecordBindTextureTypeError(const Context * context,TextureType target)6771 void RecordBindTextureTypeError(const Context *context, TextureType target)
6772 {
6773 ASSERT(!context->getStateCache().isValidBindTextureType(target));
6774
6775 switch (target)
6776 {
6777 case TextureType::Rectangle:
6778 ASSERT(!context->getExtensions().textureRectangle);
6779 context->validationError(GL_INVALID_ENUM, kTextureRectangleNotSupported);
6780 break;
6781
6782 case TextureType::_3D:
6783 case TextureType::_2DArray:
6784 ASSERT(context->getClientMajorVersion() < 3);
6785 context->validationError(GL_INVALID_ENUM, kES3Required);
6786 break;
6787
6788 case TextureType::_2DMultisample:
6789 ASSERT(context->getClientVersion() < Version(3, 1) &&
6790 !context->getExtensions().textureMultisample);
6791 context->validationError(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
6792 break;
6793
6794 case TextureType::_2DMultisampleArray:
6795 ASSERT(!context->getExtensions().textureStorageMultisample2DArrayOES);
6796 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
6797 break;
6798
6799 case TextureType::External:
6800 ASSERT(!context->getExtensions().eglImageExternalOES &&
6801 !context->getExtensions().eglStreamConsumerExternalNV);
6802 context->validationError(GL_INVALID_ENUM, kExternalTextureNotSupported);
6803 break;
6804
6805 case TextureType::VideoImage:
6806 ASSERT(!context->getExtensions().webglVideoTexture);
6807 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6808 break;
6809
6810 default:
6811 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6812 }
6813 }
6814
6815 } // namespace gl
6816