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