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