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