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