• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // validationEGL.cpp: Validation functions for generic EGL entry point parameters
8 
9 #include "libANGLE/validationEGL_autogen.h"
10 
11 #include "common/utilities.h"
12 #include "libANGLE/Config.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Device.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/EGLSync.h"
17 #include "libANGLE/Image.h"
18 #include "libANGLE/Stream.h"
19 #include "libANGLE/Surface.h"
20 #include "libANGLE/Texture.h"
21 #include "libANGLE/Thread.h"
22 #include "libANGLE/formatutils.h"
23 
24 #include <EGL/eglext.h>
25 
26 namespace egl
27 {
28 namespace
29 {
GetMaximumMipLevel(const gl::Context * context,gl::TextureType type)30 size_t GetMaximumMipLevel(const gl::Context *context, gl::TextureType type)
31 {
32     const gl::Caps &caps = context->getCaps();
33 
34     int maxDimension = 0;
35     switch (type)
36     {
37         case gl::TextureType::_2D:
38         case gl::TextureType::_2DArray:
39         case gl::TextureType::_2DMultisample:
40             maxDimension = caps.max2DTextureSize;
41             break;
42         case gl::TextureType::Rectangle:
43             maxDimension = caps.maxRectangleTextureSize;
44             break;
45         case gl::TextureType::CubeMap:
46             maxDimension = caps.maxCubeMapTextureSize;
47             break;
48         case gl::TextureType::_3D:
49             maxDimension = caps.max3DTextureSize;
50             break;
51 
52         default:
53             UNREACHABLE();
54     }
55 
56     return gl::log2(maxDimension);
57 }
58 
TextureHasNonZeroMipLevelsSpecified(const gl::Context * context,const gl::Texture * texture)59 bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture)
60 {
61     size_t maxMip = GetMaximumMipLevel(context, texture->getType());
62     for (size_t level = 1; level < maxMip; level++)
63     {
64         if (texture->getType() == gl::TextureType::CubeMap)
65         {
66             for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
67             {
68                 if (texture->getFormat(face, level).valid())
69                 {
70                     return true;
71                 }
72             }
73         }
74         else
75         {
76             if (texture->getFormat(gl::NonCubeTextureTypeToTarget(texture->getType()), level)
77                     .valid())
78             {
79                 return true;
80             }
81         }
82     }
83 
84     return false;
85 }
86 
CubeTextureHasUnspecifiedLevel0Face(const gl::Texture * texture)87 bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
88 {
89     ASSERT(texture->getType() == gl::TextureType::CubeMap);
90     for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
91     {
92         if (!texture->getFormat(face, 0).valid())
93         {
94             return true;
95         }
96     }
97 
98     return false;
99 }
100 
ValidateStreamAttribute(const ValidationContext * val,const EGLAttrib attribute,const EGLAttrib value,const DisplayExtensions & extensions)101 bool ValidateStreamAttribute(const ValidationContext *val,
102                              const EGLAttrib attribute,
103                              const EGLAttrib value,
104                              const DisplayExtensions &extensions)
105 {
106     switch (attribute)
107     {
108         case EGL_STREAM_STATE_KHR:
109         case EGL_PRODUCER_FRAME_KHR:
110         case EGL_CONSUMER_FRAME_KHR:
111             val->setError(EGL_BAD_ACCESS, "Attempt to initialize readonly parameter");
112             return false;
113         case EGL_CONSUMER_LATENCY_USEC_KHR:
114             // Technically not in spec but a latency < 0 makes no sense so we check it
115             if (value < 0)
116             {
117                 val->setError(EGL_BAD_PARAMETER, "Latency must be positive");
118                 return false;
119             }
120             break;
121         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
122             if (!extensions.streamConsumerGLTexture)
123             {
124                 val->setError(EGL_BAD_ATTRIBUTE, "Consumer GL extension not enabled");
125                 return false;
126             }
127             // Again not in spec but it should be positive anyways
128             if (value < 0)
129             {
130                 val->setError(EGL_BAD_PARAMETER, "Timeout must be positive");
131                 return false;
132             }
133             break;
134         default:
135             val->setError(EGL_BAD_ATTRIBUTE, "Invalid stream attribute");
136             return false;
137     }
138     return true;
139 }
140 
ValidateCreateImageMipLevelCommon(const ValidationContext * val,const gl::Context * context,const gl::Texture * texture,EGLAttrib level)141 bool ValidateCreateImageMipLevelCommon(const ValidationContext *val,
142                                        const gl::Context *context,
143                                        const gl::Texture *texture,
144                                        EGLAttrib level)
145 {
146     // Note that the spec EGL_create_image spec does not explicitly specify an error
147     // when the level is outside the base/max level range, but it does mention that the
148     // level "must be a part of the complete texture object <buffer>". It can be argued
149     // that out-of-range levels are not a part of the complete texture.
150     const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
151     if (level > 0 &&
152         (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
153          static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
154     {
155         val->setError(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
156         return false;
157     }
158 
159     if (level == 0 && !texture->isMipmapComplete() &&
160         TextureHasNonZeroMipLevelsSpecified(context, texture))
161     {
162         val->setError(EGL_BAD_PARAMETER,
163                       "if level is zero and the texture is incomplete, it must "
164                       "have no mip levels specified except zero.");
165         return false;
166     }
167 
168     return true;
169 }
170 
ValidateConfigAttribute(const ValidationContext * val,const Display * display,EGLAttrib attribute)171 bool ValidateConfigAttribute(const ValidationContext *val,
172                              const Display *display,
173                              EGLAttrib attribute)
174 {
175     switch (attribute)
176     {
177         case EGL_BUFFER_SIZE:
178         case EGL_ALPHA_SIZE:
179         case EGL_BLUE_SIZE:
180         case EGL_GREEN_SIZE:
181         case EGL_RED_SIZE:
182         case EGL_DEPTH_SIZE:
183         case EGL_STENCIL_SIZE:
184         case EGL_CONFIG_CAVEAT:
185         case EGL_CONFIG_ID:
186         case EGL_LEVEL:
187         case EGL_NATIVE_RENDERABLE:
188         case EGL_NATIVE_VISUAL_ID:
189         case EGL_NATIVE_VISUAL_TYPE:
190         case EGL_SAMPLES:
191         case EGL_SAMPLE_BUFFERS:
192         case EGL_SURFACE_TYPE:
193         case EGL_TRANSPARENT_TYPE:
194         case EGL_TRANSPARENT_BLUE_VALUE:
195         case EGL_TRANSPARENT_GREEN_VALUE:
196         case EGL_TRANSPARENT_RED_VALUE:
197         case EGL_BIND_TO_TEXTURE_RGB:
198         case EGL_BIND_TO_TEXTURE_RGBA:
199         case EGL_MIN_SWAP_INTERVAL:
200         case EGL_MAX_SWAP_INTERVAL:
201         case EGL_LUMINANCE_SIZE:
202         case EGL_ALPHA_MASK_SIZE:
203         case EGL_COLOR_BUFFER_TYPE:
204         case EGL_RENDERABLE_TYPE:
205         case EGL_MATCH_NATIVE_PIXMAP:
206         case EGL_CONFORMANT:
207         case EGL_MAX_PBUFFER_WIDTH:
208         case EGL_MAX_PBUFFER_HEIGHT:
209         case EGL_MAX_PBUFFER_PIXELS:
210             break;
211 
212         case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
213             if (!display->getExtensions().surfaceOrientation)
214             {
215                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
216                 return false;
217             }
218             break;
219 
220         case EGL_COLOR_COMPONENT_TYPE_EXT:
221             if (!display->getExtensions().pixelFormatFloat)
222             {
223                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_pixel_format_float is not enabled.");
224                 return false;
225             }
226             break;
227 
228         case EGL_RECORDABLE_ANDROID:
229             if (!display->getExtensions().recordable)
230             {
231                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_recordable is not enabled.");
232                 return false;
233             }
234             break;
235 
236         case EGL_FRAMEBUFFER_TARGET_ANDROID:
237             if (!display->getExtensions().framebufferTargetANDROID)
238             {
239                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_framebuffer_target is not enabled.");
240                 return false;
241             }
242             break;
243 
244         case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
245             if (!display->getExtensions().iosurfaceClientBuffer)
246             {
247                 val->setError(EGL_BAD_ATTRIBUTE,
248                               "EGL_ANGLE_iosurface_client_buffer is not enabled.");
249                 return false;
250             }
251             break;
252 
253         case EGL_Y_INVERTED_NOK:
254             if (!display->getExtensions().textureFromPixmapNOK)
255             {
256                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
257                 return false;
258             }
259             break;
260 
261         case EGL_MATCH_FORMAT_KHR:
262             if (!display->getExtensions().lockSurface3KHR)
263             {
264                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not enabled.");
265                 return false;
266             }
267             break;
268 
269         default:
270             val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
271             return false;
272     }
273 
274     return true;
275 }
276 
ValidateConfigAttributeValue(const ValidationContext * val,const Display * display,EGLAttrib attribute,EGLAttrib value)277 bool ValidateConfigAttributeValue(const ValidationContext *val,
278                                   const Display *display,
279                                   EGLAttrib attribute,
280                                   EGLAttrib value)
281 {
282     switch (attribute)
283     {
284 
285         case EGL_BIND_TO_TEXTURE_RGB:
286         case EGL_BIND_TO_TEXTURE_RGBA:
287             switch (value)
288             {
289                 case EGL_DONT_CARE:
290                 case EGL_TRUE:
291                 case EGL_FALSE:
292                     break;
293                 default:
294                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_bind_to_texture invalid attribute: 0x%X",
295                                   static_cast<uint32_t>(value));
296                     return false;
297             }
298             break;
299 
300         case EGL_COLOR_BUFFER_TYPE:
301             switch (value)
302             {
303                 case EGL_RGB_BUFFER:
304                 case EGL_LUMINANCE_BUFFER:
305                 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
306                 case EGL_DONT_CARE:
307                     break;
308                 default:
309                     val->setError(EGL_BAD_ATTRIBUTE,
310                                   "EGL_color_buffer_type invalid attribute: 0x%X",
311                                   static_cast<uint32_t>(value));
312                     return false;
313             }
314             break;
315 
316         case EGL_NATIVE_RENDERABLE:
317             switch (value)
318             {
319                 case EGL_DONT_CARE:
320                 case EGL_TRUE:
321                 case EGL_FALSE:
322                     break;
323                 default:
324                     val->setError(EGL_BAD_ATTRIBUTE,
325                                   "EGL_native_renderable invalid attribute: 0x%X",
326                                   static_cast<uint32_t>(value));
327                     return false;
328             }
329             break;
330 
331         case EGL_TRANSPARENT_TYPE:
332             switch (value)
333             {
334                 case EGL_NONE:
335                 case EGL_TRANSPARENT_RGB:
336                 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
337                 case EGL_DONT_CARE:
338                     break;
339                 default:
340                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_transparent_type invalid attribute: 0x%X",
341                                   static_cast<uint32_t>(value));
342                     return false;
343             }
344             break;
345 
346         case EGL_RECORDABLE_ANDROID:
347             switch (value)
348             {
349                 case EGL_TRUE:
350                 case EGL_FALSE:
351                 case EGL_DONT_CARE:
352                     break;
353                 default:
354                     val->setError(EGL_BAD_ATTRIBUTE,
355                                   "EGL_RECORDABLE_ANDROID invalid attribute: 0x%X",
356                                   static_cast<uint32_t>(value));
357                     return false;
358             }
359             break;
360 
361         case EGL_COLOR_COMPONENT_TYPE_EXT:
362             switch (value)
363             {
364                 case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:
365                 case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:
366                 case EGL_DONT_CARE:
367                     break;
368                 default:
369                     val->setError(EGL_BAD_ATTRIBUTE,
370                                   "EGL_COLOR_COMPONENT_TYPE_EXT invalid attribute: 0x%X",
371                                   static_cast<uint32_t>(value));
372                     return false;
373             }
374             break;
375 
376         case EGL_MATCH_FORMAT_KHR:
377             switch (value)
378             {
379                 case EGL_FORMAT_RGB_565_KHR:
380                 case EGL_FORMAT_RGBA_8888_KHR:
381                 case EGL_FORMAT_RGB_565_EXACT_KHR:
382                 case EGL_FORMAT_RGBA_8888_EXACT_KHR:
383                     break;
384                 default:
385                     val->setError(EGL_BAD_ATTRIBUTE,
386                                   "EGL_KHR_lock_surface3 invalid attribute: 0x%X",
387                                   static_cast<uint32_t>(value));
388                     return false;
389             }
390             break;
391 
392         default:
393             break;
394     }
395 
396     return true;
397 }
398 
ValidateConfigAttributes(const ValidationContext * val,const Display * display,const AttributeMap & attributes)399 bool ValidateConfigAttributes(const ValidationContext *val,
400                               const Display *display,
401                               const AttributeMap &attributes)
402 {
403     ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateConfigAttribute));
404 
405     for (const auto &attrib : attributes)
406     {
407         EGLAttrib pname = attrib.first;
408         EGLAttrib value = attrib.second;
409         ANGLE_VALIDATION_TRY(ValidateConfigAttributeValue(val, display, pname, value));
410     }
411 
412     return true;
413 }
414 
ValidateColorspaceAttribute(const ValidationContext * val,const DisplayExtensions & displayExtensions,EGLAttrib colorSpace)415 bool ValidateColorspaceAttribute(const ValidationContext *val,
416                                  const DisplayExtensions &displayExtensions,
417                                  EGLAttrib colorSpace)
418 {
419     switch (colorSpace)
420     {
421         case EGL_GL_COLORSPACE_SRGB:
422             break;
423         case EGL_GL_COLORSPACE_LINEAR:
424             break;
425         case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
426             if (!displayExtensions.glColorspaceDisplayP3Linear)
427             {
428                 val->setError(EGL_BAD_ATTRIBUTE,
429                               "EXT_gl_colorspace_display_p3_linear is not available.");
430                 return false;
431             }
432             break;
433         case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
434             if (!displayExtensions.glColorspaceDisplayP3)
435             {
436                 val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_display_p3 is not available.");
437                 return false;
438             }
439             break;
440         case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
441             if (!displayExtensions.glColorspaceDisplayP3Passthrough)
442             {
443                 val->setError(EGL_BAD_ATTRIBUTE,
444                               "EGL_EXT_gl_colorspace_display_p3_passthrough is not available.");
445                 return false;
446             }
447             break;
448         case EGL_GL_COLORSPACE_SCRGB_EXT:
449             if (!displayExtensions.glColorspaceScrgb)
450             {
451                 val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_scrgb is not available.");
452                 return false;
453             }
454             break;
455         case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
456             if (!displayExtensions.glColorspaceScrgbLinear)
457             {
458                 val->setError(EGL_BAD_ATTRIBUTE,
459                               "EXT_gl_colorspace_scrgb_linear is not available.");
460                 return false;
461             }
462             break;
463         default:
464             val->setError(EGL_BAD_ATTRIBUTE);
465             return false;
466     }
467     return true;
468 }
ValidatePlatformType(const ValidationContext * val,const ClientExtensions & clientExtensions,EGLAttrib platformType)469 bool ValidatePlatformType(const ValidationContext *val,
470                           const ClientExtensions &clientExtensions,
471                           EGLAttrib platformType)
472 {
473     switch (platformType)
474     {
475         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
476             break;
477 
478         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
479         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
480             if (!clientExtensions.platformANGLED3D)
481             {
482                 val->setError(EGL_BAD_ATTRIBUTE, "Direct3D platform is unsupported.");
483                 return false;
484             }
485             break;
486 
487         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
488         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
489             if (!clientExtensions.platformANGLEOpenGL)
490             {
491                 val->setError(EGL_BAD_ATTRIBUTE, "OpenGL platform is unsupported.");
492                 return false;
493             }
494             break;
495 
496         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
497             if (!clientExtensions.platformANGLENULL)
498             {
499                 val->setError(EGL_BAD_ATTRIBUTE,
500                               "Display type EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
501                               "requires EGL_ANGLE_platform_angle_null.");
502                 return false;
503             }
504             break;
505 
506         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
507             if (!clientExtensions.platformANGLEVulkan)
508             {
509                 val->setError(EGL_BAD_ATTRIBUTE, "Vulkan platform is unsupported.");
510                 return false;
511             }
512             break;
513 
514         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
515             if (!clientExtensions.platformANGLEMetal)
516             {
517                 val->setError(EGL_BAD_ATTRIBUTE, "Metal platform is unsupported.");
518                 return false;
519             }
520             break;
521 
522         default:
523             val->setError(EGL_BAD_ATTRIBUTE, "Unknown platform type.");
524             return false;
525     }
526 
527     return true;
528 }
529 
ValidateGetPlatformDisplayCommon(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)530 bool ValidateGetPlatformDisplayCommon(const ValidationContext *val,
531                                       EGLenum platform,
532                                       const void *native_display,
533                                       const AttributeMap &attribMap)
534 {
535     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
536 
537     switch (platform)
538     {
539         case EGL_PLATFORM_ANGLE_ANGLE:
540             if (!clientExtensions.platformANGLE)
541             {
542                 val->setError(EGL_BAD_PARAMETER, "Platform ANGLE extension is not active");
543                 return false;
544             }
545             break;
546         case EGL_PLATFORM_DEVICE_EXT:
547             if (!clientExtensions.platformDevice)
548             {
549                 val->setError(EGL_BAD_PARAMETER, "Platform Device extension is not active");
550                 return false;
551             }
552             break;
553         default:
554             val->setError(EGL_BAD_CONFIG, "Bad platform type.");
555             return false;
556     }
557 
558     attribMap.initializeWithoutValidation();
559 
560     if (platform == EGL_PLATFORM_ANGLE_ANGLE)
561     {
562         EGLAttrib platformType       = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
563         bool enableAutoTrimSpecified = false;
564         bool enableD3D11on12         = false;
565         bool presentPathSpecified    = false;
566         bool luidSpecified           = false;
567 
568         Optional<EGLAttrib> majorVersion;
569         Optional<EGLAttrib> minorVersion;
570         Optional<EGLAttrib> deviceType;
571         Optional<EGLAttrib> eglHandle;
572 
573         for (const auto &curAttrib : attribMap)
574         {
575             const EGLAttrib value = curAttrib.second;
576 
577             switch (curAttrib.first)
578             {
579                 case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
580                 {
581                     ANGLE_VALIDATION_TRY(ValidatePlatformType(val, clientExtensions, value));
582                     platformType = value;
583                     break;
584                 }
585 
586                 case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
587                     if (value != EGL_DONT_CARE)
588                     {
589                         majorVersion = value;
590                     }
591                     break;
592 
593                 case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
594                     if (value != EGL_DONT_CARE)
595                     {
596                         minorVersion = value;
597                     }
598                     break;
599 
600                 case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
601                     switch (value)
602                     {
603                         case EGL_TRUE:
604                         case EGL_FALSE:
605                             break;
606                         default:
607                             val->setError(EGL_BAD_ATTRIBUTE, "Invalid automatic trim attribute");
608                             return false;
609                     }
610                     enableAutoTrimSpecified = true;
611                     break;
612 
613                 case EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE:
614                     if (!clientExtensions.platformANGLED3D ||
615                         !clientExtensions.platformANGLED3D11ON12)
616                     {
617                         val->setError(EGL_BAD_ATTRIBUTE,
618                                       "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE extension not active.");
619                         return false;
620                     }
621 
622                     switch (value)
623                     {
624                         case EGL_TRUE:
625                         case EGL_FALSE:
626                             break;
627                         default:
628                             val->setError(EGL_BAD_ATTRIBUTE, "Invalid D3D11on12 attribute");
629                             return false;
630                     }
631                     enableD3D11on12 = true;
632                     break;
633 
634                 case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
635                     if (!clientExtensions.experimentalPresentPath)
636                     {
637                         val->setError(EGL_BAD_ATTRIBUTE,
638                                       "EGL_ANGLE_experimental_present_path extension not active");
639                         return false;
640                     }
641 
642                     switch (value)
643                     {
644                         case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
645                         case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
646                             break;
647                         default:
648                             val->setError(EGL_BAD_ATTRIBUTE,
649                                           "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE");
650                             return false;
651                     }
652                     presentPathSpecified = true;
653                     break;
654 
655                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
656                     switch (value)
657                     {
658                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
659                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
660                             break;
661 
662                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
663                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
664                             if (!clientExtensions.platformANGLED3D)
665                             {
666                                 val->setError(EGL_BAD_ATTRIBUTE,
667                                               "EGL_ANGLE_platform_angle_d3d is not supported");
668                                 return false;
669                             }
670                             break;
671 
672                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE:
673                             if (!clientExtensions.platformANGLEDeviceTypeEGLANGLE)
674                             {
675                                 val->setError(EGL_BAD_ATTRIBUTE,
676                                               "EGL_ANGLE_platform_angle_device_type_"
677                                               "egl_angle is not supported");
678                                 return false;
679                             }
680                             break;
681 
682                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
683                             if (!clientExtensions.platformANGLEDeviceTypeSwiftShader)
684                             {
685                                 val->setError(EGL_BAD_ATTRIBUTE,
686                                               "EGL_ANGLE_platform_angle_device_type_"
687                                               "swiftshader is not supported");
688                                 return false;
689                             }
690                             break;
691 
692                         default:
693                             val->setError(EGL_BAD_ATTRIBUTE,
694                                           "Invalid value for "
695                                           "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
696                                           "attrib");
697                             return false;
698                     }
699                     deviceType = value;
700                     break;
701 
702                 case EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE:
703                     if (!clientExtensions.platformANGLE)
704                     {
705                         val->setError(EGL_BAD_ATTRIBUTE,
706                                       "EGL_ANGLE_platform_angle extension not active");
707                         return false;
708                     }
709                     if (value != EGL_TRUE && value != EGL_FALSE && value != EGL_DONT_CARE)
710                     {
711                         val->setError(EGL_BAD_ATTRIBUTE,
712                                       "EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE "
713                                       "must be EGL_TRUE, EGL_FALSE, or "
714                                       "EGL_DONT_CARE.");
715                         return false;
716                     }
717                     break;
718 
719                 case EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE:
720                     if (value != EGL_DONT_CARE)
721                     {
722                         eglHandle = value;
723                     }
724                     break;
725 
726                 case EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE:
727                 case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
728                     luidSpecified = true;
729                     break;
730                 case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE:
731                     // The property does not have an effect if it's not active, so do not check
732                     // for non-support.
733                     switch (value)
734                     {
735                         case EGL_FALSE:
736                         case EGL_TRUE:
737                             break;
738                         default:
739                             val->setError(EGL_BAD_ATTRIBUTE,
740                                           "Invalid value for "
741                                           "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
742                                           "EAGL_ANGLE attrib");
743                             return false;
744                     }
745                     break;
746                 case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE:
747                     // The property does not have an effect if it's not active, so do not check
748                     // for non-support.
749                     switch (value)
750                     {
751                         case EGL_FALSE:
752                         case EGL_TRUE:
753                             break;
754                         default:
755                             val->setError(EGL_BAD_ATTRIBUTE,
756                                           "Invalid value for "
757                                           "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
758                                           "CGL_ANGLE attrib");
759                             return false;
760                     }
761                     break;
762                 default:
763                     break;
764             }
765         }
766 
767         if (!majorVersion.valid() && minorVersion.valid())
768         {
769             val->setError(EGL_BAD_ATTRIBUTE,
770                           "Must specify major version if you specify a minor version.");
771             return false;
772         }
773 
774         if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE &&
775             platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
776         {
777             val->setError(EGL_BAD_ATTRIBUTE,
778                           "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a "
779                           "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
780             return false;
781         }
782 
783         if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
784         {
785             val->setError(EGL_BAD_ATTRIBUTE,
786                           "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE "
787                           "requires a device type of "
788                           "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
789             return false;
790         }
791 
792         if (enableD3D11on12)
793         {
794             if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
795             {
796                 val->setError(EGL_BAD_ATTRIBUTE,
797                               "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE "
798                               "requires a platform type of "
799                               "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
800                 return false;
801             }
802 
803             if (deviceType.valid() && deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE &&
804                 deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE)
805             {
806                 val->setError(EGL_BAD_ATTRIBUTE,
807                               "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE requires a device "
808                               "type of EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE "
809                               "or EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE");
810                 return false;
811             }
812         }
813 
814         if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
815         {
816             val->setError(EGL_BAD_ATTRIBUTE,
817                           "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a "
818                           "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
819             return false;
820         }
821 
822         if (luidSpecified)
823         {
824             if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
825             {
826                 val->setError(EGL_BAD_ATTRIBUTE,
827                               "EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE and "
828                               "EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE "
829                               "require a platform type of "
830                               "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
831                 return false;
832             }
833 
834             if (attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0) == 0 &&
835                 attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0) == 0)
836             {
837                 val->setError(EGL_BAD_ATTRIBUTE,
838                               "If either EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE "
839                               "and/or EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE are "
840                               "specified, at least one must non-zero.");
841                 return false;
842             }
843         }
844 
845         if (deviceType.valid())
846         {
847             switch (deviceType.value())
848             {
849                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
850                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
851                     if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
852                         platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
853                     {
854                         val->setError(EGL_BAD_ATTRIBUTE,
855                                       "This device type requires a "
856                                       "platform type of EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or "
857                                       "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE.");
858                         return false;
859                     }
860                     break;
861 
862                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
863                     if (platformType != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
864                     {
865                         val->setError(EGL_BAD_ATTRIBUTE,
866                                       "This device type requires a "
867                                       "platform type of EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.");
868                         return false;
869                     }
870                     break;
871 
872                 default:
873                     break;
874             }
875         }
876 
877         if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
878         {
879             if ((majorVersion.valid() && majorVersion.value() != 1) ||
880                 (minorVersion.valid() && minorVersion.value() != 0))
881             {
882                 val->setError(EGL_BAD_ATTRIBUTE,
883                               "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently "
884                               "only supports Vulkan 1.0.");
885                 return false;
886             }
887         }
888 
889         if (eglHandle.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
890             platformType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
891         {
892             val->setError(EGL_BAD_ATTRIBUTE,
893                           "EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE requires a "
894                           "device type of EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE.");
895             return false;
896         }
897     }
898     else if (platform == EGL_PLATFORM_DEVICE_EXT)
899     {
900         const Device *eglDevice = static_cast<const Device *>(native_display);
901         if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
902         {
903             val->setError(EGL_BAD_ATTRIBUTE,
904                           "native_display should be a valid EGL device if "
905                           "platform equals EGL_PLATFORM_DEVICE_EXT");
906             return false;
907         }
908     }
909     else
910     {
911         UNREACHABLE();
912     }
913 
914     if (attribMap.contains(EGL_POWER_PREFERENCE_ANGLE))
915     {
916         if (!clientExtensions.displayPowerPreferenceANGLE)
917         {
918             val->setError(EGL_BAD_ATTRIBUTE,
919                           "Attribute EGL_POWER_PREFERENCE_ANGLE "
920                           "requires EGL_ANGLE_display_power_preference.");
921             return false;
922         }
923         EGLAttrib value = attribMap.get(EGL_POWER_PREFERENCE_ANGLE, 0);
924         if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
925         {
926             val->setError(EGL_BAD_ATTRIBUTE,
927                           "EGL_POWER_PREFERENCE_ANGLE must be "
928                           "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
929             return false;
930         }
931     }
932 
933     if (attribMap.contains(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE))
934     {
935         if (!clientExtensions.featureControlANGLE)
936         {
937             val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
938             return false;
939         }
940         else if (attribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0) == 0)
941         {
942             val->setError(EGL_BAD_ATTRIBUTE,
943                           "EGL_FEATURE_OVERRIDES_ENABLED_ANGLE must be a valid pointer");
944             return false;
945         }
946     }
947     if (attribMap.contains(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE))
948     {
949         if (!clientExtensions.featureControlANGLE)
950         {
951             val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
952             return false;
953         }
954         else if (attribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0) == 0)
955         {
956             val->setError(EGL_BAD_ATTRIBUTE,
957                           "EGL_FEATURE_OVERRIDES_DISABLED_ANGLE must be a valid pointer");
958             return false;
959         }
960     }
961 
962     return true;
963 }
964 
ValidateStream(const ValidationContext * val,const Display * display,const Stream * stream)965 bool ValidateStream(const ValidationContext *val, const Display *display, const Stream *stream)
966 {
967     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
968 
969     const DisplayExtensions &displayExtensions = display->getExtensions();
970     if (!displayExtensions.stream)
971     {
972         val->setError(EGL_BAD_ACCESS, "Stream extension not active");
973         return false;
974     }
975 
976     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
977     {
978         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
979         return false;
980     }
981 
982     return true;
983 }
984 
ValidateLabeledObject(const ValidationContext * val,const Display * display,ObjectType objectType,EGLObjectKHR object,LabeledObject ** outLabeledObject)985 bool ValidateLabeledObject(const ValidationContext *val,
986                            const Display *display,
987                            ObjectType objectType,
988                            EGLObjectKHR object,
989                            LabeledObject **outLabeledObject)
990 {
991     switch (objectType)
992     {
993         case ObjectType::Context:
994         {
995             gl::Context *context = static_cast<gl::Context *>(object);
996             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
997             *outLabeledObject = context;
998             break;
999         }
1000 
1001         case ObjectType::Display:
1002         {
1003             ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
1004             if (display != object)
1005             {
1006                 if (val)
1007                 {
1008                     val->setError(EGL_BAD_PARAMETER,
1009                                   "when object type is EGL_OBJECT_DISPLAY_KHR, the "
1010                                   "object must be the same as the display.");
1011                 }
1012                 return false;
1013             }
1014 
1015             *outLabeledObject = static_cast<Display *>(object);
1016             break;
1017         }
1018 
1019         case ObjectType::Image:
1020         {
1021             Image *image = static_cast<Image *>(object);
1022             ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
1023             *outLabeledObject = image;
1024             break;
1025         }
1026 
1027         case ObjectType::Stream:
1028         {
1029             Stream *stream = static_cast<Stream *>(object);
1030             ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
1031             *outLabeledObject = stream;
1032             break;
1033         }
1034 
1035         case ObjectType::Surface:
1036         {
1037             Surface *surface = static_cast<Surface *>(object);
1038             ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
1039             *outLabeledObject = surface;
1040             break;
1041         }
1042 
1043         case ObjectType::Sync:
1044         {
1045             Sync *sync = static_cast<Sync *>(object);
1046             ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
1047             *outLabeledObject = sync;
1048             break;
1049         }
1050 
1051         case ObjectType::Thread:
1052         {
1053             ASSERT(val);
1054             *outLabeledObject = val->eglThread;
1055             break;
1056         }
1057 
1058         default:
1059             if (val)
1060             {
1061                 val->setError(EGL_BAD_PARAMETER, "unknown object type.");
1062             }
1063             return false;
1064     }
1065 
1066     return true;
1067 }
1068 
1069 // This is a common sub-check of Display status that's shared by multiple functions
ValidateDisplayPointer(const ValidationContext * val,const Display * display)1070 bool ValidateDisplayPointer(const ValidationContext *val, const Display *display)
1071 {
1072     if (display == EGL_NO_DISPLAY)
1073     {
1074         if (val)
1075         {
1076             val->setError(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY.");
1077         }
1078         return false;
1079     }
1080 
1081     if (!Display::isValidDisplay(display))
1082     {
1083         if (val)
1084         {
1085             val->setError(EGL_BAD_DISPLAY, "display is not a valid display: 0x%p", display);
1086         }
1087         return false;
1088     }
1089 
1090     return true;
1091 }
1092 
ValidCompositorTimingName(CompositorTiming name)1093 bool ValidCompositorTimingName(CompositorTiming name)
1094 {
1095     switch (name)
1096     {
1097         case CompositorTiming::CompositeDeadline:
1098         case CompositorTiming::CompositInterval:
1099         case CompositorTiming::CompositToPresentLatency:
1100             return true;
1101 
1102         default:
1103             return false;
1104     }
1105 }
1106 
ValidTimestampType(Timestamp timestamp)1107 bool ValidTimestampType(Timestamp timestamp)
1108 {
1109     switch (timestamp)
1110     {
1111         case Timestamp::RequestedPresentTime:
1112         case Timestamp::RenderingCompleteTime:
1113         case Timestamp::CompositionLatchTime:
1114         case Timestamp::FirstCompositionStartTime:
1115         case Timestamp::LastCompositionStartTime:
1116         case Timestamp::FirstCompositionGPUFinishedTime:
1117         case Timestamp::DisplayPresentTime:
1118         case Timestamp::DequeueReadyTime:
1119         case Timestamp::ReadsDoneTime:
1120             return true;
1121 
1122         default:
1123             return false;
1124     }
1125 }
1126 
ValidateCompatibleSurface(const ValidationContext * val,const Display * display,const gl::Context * context,const Surface * surface)1127 bool ValidateCompatibleSurface(const ValidationContext *val,
1128                                const Display *display,
1129                                const gl::Context *context,
1130                                const Surface *surface)
1131 {
1132     const Config *contextConfig = context->getConfig();
1133     const Config *surfaceConfig = surface->getConfig();
1134 
1135     // Surface compatible with client API - only OPENGL_ES supported
1136     switch (context->getClientMajorVersion())
1137     {
1138         case 1:
1139             if (!(surfaceConfig->renderableType & EGL_OPENGL_ES_BIT))
1140             {
1141                 val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 1.x.");
1142                 return false;
1143             }
1144             break;
1145         case 2:
1146             if (!(surfaceConfig->renderableType & EGL_OPENGL_ES2_BIT))
1147             {
1148                 val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 2.x.");
1149                 return false;
1150             }
1151             break;
1152         case 3:
1153             if (!(surfaceConfig->renderableType & (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT)))
1154             {
1155                 val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 3.x.");
1156                 return false;
1157             }
1158             break;
1159         default:
1160             val->setError(EGL_BAD_MATCH, "Surface not compatible with Context API.");
1161             return false;
1162     }
1163 
1164     // EGL KHR no config context
1165     if (context->getConfig() == EGL_NO_CONFIG_KHR)
1166     {
1167         const DisplayExtensions &displayExtensions = display->getExtensions();
1168         if (displayExtensions.noConfigContext)
1169         {
1170             return true;
1171         }
1172         val->setError(EGL_BAD_MATCH, "Context with no config is not supported.");
1173         return false;
1174     }
1175 
1176     // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
1177 
1178     bool colorBufferCompat = surfaceConfig->colorBufferType == contextConfig->colorBufferType;
1179     if (!colorBufferCompat)
1180     {
1181         val->setError(EGL_BAD_MATCH, "Color buffer types are not compatible.");
1182         return false;
1183     }
1184 
1185     bool colorCompat = surfaceConfig->redSize == contextConfig->redSize &&
1186                        surfaceConfig->greenSize == contextConfig->greenSize &&
1187                        surfaceConfig->blueSize == contextConfig->blueSize &&
1188                        surfaceConfig->alphaSize == contextConfig->alphaSize &&
1189                        surfaceConfig->luminanceSize == contextConfig->luminanceSize;
1190     if (!colorCompat)
1191     {
1192         val->setError(EGL_BAD_MATCH, "Color buffer sizes are not compatible.");
1193         return false;
1194     }
1195 
1196     bool componentTypeCompat =
1197         surfaceConfig->colorComponentType == contextConfig->colorComponentType;
1198     if (!componentTypeCompat)
1199     {
1200         val->setError(EGL_BAD_MATCH, "Color buffer component types are not compatible.");
1201         return false;
1202     }
1203 
1204     bool dsCompat = surfaceConfig->depthSize == contextConfig->depthSize &&
1205                     surfaceConfig->stencilSize == contextConfig->stencilSize;
1206     if (!dsCompat)
1207     {
1208         val->setError(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible.");
1209         return false;
1210     }
1211 
1212     bool surfaceTypeCompat = (surfaceConfig->surfaceType & contextConfig->surfaceType) != 0;
1213     if (!surfaceTypeCompat)
1214     {
1215         val->setError(EGL_BAD_MATCH, "Surface type is not compatible.");
1216         return false;
1217     }
1218 
1219     return true;
1220 }
1221 
ValidateCreateSyncBase(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs,bool isExt)1222 bool ValidateCreateSyncBase(const ValidationContext *val,
1223                             const Display *display,
1224                             EGLenum type,
1225                             const AttributeMap &attribs,
1226                             bool isExt)
1227 {
1228     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
1229 
1230     attribs.initializeWithoutValidation();
1231 
1232     gl::Context *currentContext  = val->eglThread->getContext();
1233     egl::Display *currentDisplay = currentContext ? currentContext->getDisplay() : nullptr;
1234 
1235     switch (type)
1236     {
1237         case EGL_SYNC_FENCE_KHR:
1238             if (!attribs.isEmpty())
1239             {
1240                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1241                 return false;
1242             }
1243 
1244             if (!display->getExtensions().fenceSync)
1245             {
1246                 val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
1247                 return false;
1248             }
1249 
1250             if (display != currentDisplay)
1251             {
1252                 val->setError(EGL_BAD_MATCH,
1253                               "CreateSync can only be called on the current display");
1254                 return false;
1255             }
1256 
1257             ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
1258 
1259             if (!currentContext->getExtensions().EGLSyncOES)
1260             {
1261                 val->setError(EGL_BAD_MATCH,
1262                               "EGL_SYNC_FENCE_KHR cannot be used without "
1263                               "GL_OES_EGL_sync support.");
1264                 return false;
1265             }
1266             break;
1267 
1268         case EGL_SYNC_NATIVE_FENCE_ANDROID:
1269             if (!display->getExtensions().fenceSync)
1270             {
1271                 val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
1272                 return false;
1273             }
1274 
1275             if (!display->getExtensions().nativeFenceSyncANDROID)
1276             {
1277                 val->setError(EGL_BAD_DISPLAY,
1278                               "EGL_ANDROID_native_fence_sync extension is not available.");
1279                 return false;
1280             }
1281 
1282             if (display != currentDisplay)
1283             {
1284                 val->setError(EGL_BAD_MATCH,
1285                               "CreateSync can only be called on the current display");
1286                 return false;
1287             }
1288 
1289             ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
1290 
1291             if (!currentContext->getExtensions().EGLSyncOES)
1292             {
1293                 val->setError(EGL_BAD_MATCH,
1294                               "EGL_SYNC_FENCE_KHR cannot be used without "
1295                               "GL_OES_EGL_sync support.");
1296                 return false;
1297             }
1298 
1299             for (const auto &attributeIter : attribs)
1300             {
1301                 EGLAttrib attribute = attributeIter.first;
1302 
1303                 switch (attribute)
1304                 {
1305                     case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
1306                         break;
1307 
1308                     default:
1309                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1310                         return false;
1311                 }
1312             }
1313             break;
1314 
1315         case EGL_SYNC_REUSABLE_KHR:
1316             if (!attribs.isEmpty())
1317             {
1318                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1319                 return false;
1320             }
1321 
1322             if (!display->getExtensions().reusableSyncKHR)
1323             {
1324                 val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
1325                 return false;
1326             }
1327             break;
1328 
1329         default:
1330             if (isExt)
1331             {
1332                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid type parameter");
1333                 return false;
1334             }
1335             else
1336             {
1337                 val->setError(EGL_BAD_PARAMETER, "Invalid type parameter");
1338                 return false;
1339             }
1340     }
1341 
1342     return true;
1343 }
1344 
ValidateGetSyncAttribBase(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute)1345 bool ValidateGetSyncAttribBase(const ValidationContext *val,
1346                                const Display *display,
1347                                const Sync *sync,
1348                                EGLint attribute)
1349 {
1350     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
1351 
1352     switch (attribute)
1353     {
1354         case EGL_SYNC_CONDITION_KHR:
1355             switch (sync->getType())
1356             {
1357                 case EGL_SYNC_FENCE_KHR:
1358                 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1359                     break;
1360 
1361                 default:
1362                     val->setError(EGL_BAD_ATTRIBUTE,
1363                                   "EGL_SYNC_CONDITION_KHR is not valid for this sync type.");
1364                     return false;
1365             }
1366             break;
1367 
1368         // The following attributes are accepted by all types
1369         case EGL_SYNC_TYPE_KHR:
1370         case EGL_SYNC_STATUS_KHR:
1371             break;
1372 
1373         default:
1374             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1375             return false;
1376     }
1377 
1378     return true;
1379 }
1380 
ValidateQueryDisplayAttribBase(const ValidationContext * val,const Display * display,const EGLint attribute)1381 bool ValidateQueryDisplayAttribBase(const ValidationContext *val,
1382                                     const Display *display,
1383                                     const EGLint attribute)
1384 {
1385     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
1386 
1387     switch (attribute)
1388     {
1389         case EGL_DEVICE_EXT:
1390             if (!Display::GetClientExtensions().deviceQueryEXT)
1391             {
1392                 val->setError(EGL_BAD_DISPLAY, "EGL_EXT_device_query extension is not available.");
1393                 return false;
1394             }
1395             break;
1396 
1397         case EGL_FEATURE_COUNT_ANGLE:
1398             if (!Display::GetClientExtensions().featureControlANGLE)
1399             {
1400                 val->setError(EGL_BAD_DISPLAY,
1401                               "EGL_ANGLE_feature_control extension is not available.");
1402                 return false;
1403             }
1404             break;
1405 
1406         default:
1407             val->setError(EGL_BAD_ATTRIBUTE, "attribute is not valid.");
1408             return false;
1409     }
1410 
1411     return true;
1412 }
1413 
ValidateCreateContextAttribute(const ValidationContext * val,const Display * display,EGLAttrib attribute)1414 bool ValidateCreateContextAttribute(const ValidationContext *val,
1415                                     const Display *display,
1416                                     EGLAttrib attribute)
1417 {
1418     switch (attribute)
1419     {
1420         case EGL_CONTEXT_CLIENT_VERSION:
1421         case EGL_CONTEXT_MINOR_VERSION:
1422         case EGL_CONTEXT_FLAGS_KHR:
1423         case EGL_CONTEXT_OPENGL_DEBUG:
1424             break;
1425 
1426         case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
1427             // Only valid for OpenGL (non-ES) contexts
1428             val->setError(EGL_BAD_ATTRIBUTE);
1429             return false;
1430 
1431         case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
1432             if (!display->getExtensions().createContextRobustness)
1433             {
1434                 val->setError(EGL_BAD_ATTRIBUTE);
1435                 return false;
1436             }
1437             break;
1438 
1439         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
1440             val->setError(EGL_BAD_ATTRIBUTE,
1441                           "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR is not"
1442                           " valid for GLES with EGL 1.4 and KHR_create_context. Use"
1443                           " EXT_create_context_robustness.");
1444             return false;
1445 
1446         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
1447             if (!display->getExtensions().createContextRobustness)
1448             {
1449                 val->setError(EGL_BAD_ATTRIBUTE);
1450                 return false;
1451             }
1452             break;
1453 
1454         case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
1455             if (!display->getExtensions().createContextNoError)
1456             {
1457                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
1458                 return false;
1459             }
1460             break;
1461 
1462         case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
1463             if (!display->getExtensions().createContextWebGLCompatibility)
1464             {
1465                 val->setError(EGL_BAD_ATTRIBUTE,
1466                               "Attribute "
1467                               "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
1468                               "EGL_ANGLE_create_context_webgl_compatibility.");
1469                 return false;
1470             }
1471             break;
1472 
1473         case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
1474             if (!display->getExtensions().createContextBindGeneratesResource)
1475             {
1476                 val->setError(EGL_BAD_ATTRIBUTE,
1477                               "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
1478                               "EGL_CHROMIUM_create_context_bind_generates_resource.");
1479                 return false;
1480             }
1481             break;
1482 
1483         case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
1484             if (!display->getExtensions().displayTextureShareGroup)
1485             {
1486                 val->setError(EGL_BAD_ATTRIBUTE,
1487                               "Attribute "
1488                               "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
1489                               "EGL_ANGLE_display_texture_share_group.");
1490                 return false;
1491             }
1492             break;
1493 
1494         case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
1495             if (!display->getExtensions().displayTextureShareGroup)
1496             {
1497                 val->setError(EGL_BAD_ATTRIBUTE,
1498                               "Attribute "
1499                               "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE requires "
1500                               "EGL_ANGLE_display_semaphore_share_group.");
1501                 return false;
1502             }
1503             break;
1504 
1505         case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
1506             if (!display->getExtensions().createContextClientArrays)
1507             {
1508                 val->setError(EGL_BAD_ATTRIBUTE,
1509                               "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
1510                               "EGL_ANGLE_create_context_client_arrays.");
1511                 return false;
1512             }
1513             break;
1514 
1515         case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
1516             if (!display->getExtensions().programCacheControlANGLE)
1517             {
1518                 val->setError(EGL_BAD_ATTRIBUTE,
1519                               "Attribute EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE "
1520                               "requires EGL_ANGLE_program_cache_control.");
1521                 return false;
1522             }
1523             break;
1524 
1525         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1526             if (!display->getExtensions().robustResourceInitializationANGLE)
1527             {
1528                 val->setError(EGL_BAD_ATTRIBUTE,
1529                               "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1530                               "requires EGL_ANGLE_robust_resource_initialization.");
1531                 return false;
1532             }
1533             break;
1534 
1535         case EGL_EXTENSIONS_ENABLED_ANGLE:
1536             if (!display->getExtensions().createContextExtensionsEnabled)
1537             {
1538                 val->setError(EGL_BAD_ATTRIBUTE,
1539                               "Attribute EGL_EXTENSIONS_ENABLED_ANGLE "
1540                               "requires EGL_ANGLE_create_context_extensions_enabled.");
1541                 return false;
1542             }
1543             break;
1544 
1545         case EGL_POWER_PREFERENCE_ANGLE:
1546             if (!display->getExtensions().powerPreference)
1547             {
1548                 val->setError(EGL_BAD_ATTRIBUTE,
1549                               "Attribute EGL_POWER_PREFERENCE_ANGLE "
1550                               "requires EGL_ANGLE_power_preference.");
1551                 return false;
1552             }
1553             break;
1554 
1555         case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
1556             if (!display->getExtensions().createContextBackwardsCompatible)
1557             {
1558                 val->setError(EGL_BAD_ATTRIBUTE,
1559                               "Attribute EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE "
1560                               "requires EGL_ANGLE_create_context_backwards_compatible.");
1561                 return false;
1562             }
1563             break;
1564 
1565         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
1566             if (!display->getExtensions().contextPriority)
1567             {
1568                 val->setError(EGL_BAD_ATTRIBUTE,
1569                               "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
1570                               "extension EGL_IMG_context_priority.");
1571                 return false;
1572             }
1573             break;
1574 
1575         case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
1576             if (!display->getExtensions().robustnessVideoMemoryPurgeNV)
1577             {
1578                 val->setError(EGL_BAD_ATTRIBUTE,
1579                               "Attribute EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV requires "
1580                               "extension EGL_NV_robustness_video_memory_purge.");
1581                 return false;
1582             }
1583             break;
1584 
1585         case EGL_EXTERNAL_CONTEXT_ANGLE:
1586             if (!display->getExtensions().externalContextAndSurface)
1587             {
1588                 val->setError(EGL_BAD_ATTRIBUTE,
1589                               "Attribute "
1590                               "EGL_EXTERNAL_CONTEXT_ANGLE requires "
1591                               "EGL_ANGLE_external_context_and_surface.");
1592                 return false;
1593             }
1594             break;
1595         case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
1596             if (!display->getExtensions().externalContextAndSurface)
1597             {
1598                 val->setError(EGL_BAD_ATTRIBUTE,
1599                               "Attribute "
1600                               "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE requires "
1601                               "EGL_ANGLE_external_context_and_surface.");
1602                 return false;
1603             }
1604             break;
1605 
1606         case EGL_PROTECTED_CONTENT_EXT:
1607             if (!display->getExtensions().protectedContentEXT)
1608             {
1609                 val->setError(EGL_BAD_ATTRIBUTE,
1610                               "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
1611                               "extension EGL_EXT_protected_content.");
1612                 return false;
1613             }
1614             break;
1615 
1616         case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
1617             if (!display->getExtensions().contextVirtualizationANGLE)
1618             {
1619                 val->setError(EGL_BAD_ATTRIBUTE,
1620                               "Attribute EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE requires "
1621                               "extension EGL_ANGLE_context_virtualization.");
1622                 return false;
1623             }
1624             break;
1625 
1626         default:
1627             val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
1628             return false;
1629     }
1630 
1631     return true;
1632 }
1633 
ValidateCreateContextAttributeValue(const ValidationContext * val,const Display * display,const gl::Context * shareContext,EGLAttrib attribute,EGLAttrib value)1634 bool ValidateCreateContextAttributeValue(const ValidationContext *val,
1635                                          const Display *display,
1636                                          const gl::Context *shareContext,
1637                                          EGLAttrib attribute,
1638                                          EGLAttrib value)
1639 {
1640     switch (attribute)
1641     {
1642         case EGL_CONTEXT_CLIENT_VERSION:
1643         case EGL_CONTEXT_MINOR_VERSION:
1644         case EGL_CONTEXT_OPENGL_DEBUG:
1645         case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
1646             break;
1647 
1648         case EGL_CONTEXT_FLAGS_KHR:
1649         {
1650             // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
1651             constexpr EGLint kValidContextFlags =
1652                 (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
1653             if ((value & ~kValidContextFlags) != 0)
1654             {
1655                 val->setError(EGL_BAD_ATTRIBUTE);
1656                 return false;
1657             }
1658             break;
1659         }
1660 
1661         case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
1662             if (value != EGL_TRUE && value != EGL_FALSE)
1663             {
1664                 val->setError(EGL_BAD_ATTRIBUTE);
1665                 return false;
1666             }
1667             break;
1668 
1669         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
1670             if (value != EGL_LOSE_CONTEXT_ON_RESET_EXT && value != EGL_NO_RESET_NOTIFICATION_EXT)
1671             {
1672                 val->setError(EGL_BAD_ATTRIBUTE);
1673                 return false;
1674             }
1675 
1676             if (shareContext && shareContext->isResetNotificationEnabled() !=
1677                                     (value == EGL_LOSE_CONTEXT_ON_RESET_EXT))
1678             {
1679                 val->setError(EGL_BAD_MATCH);
1680                 return false;
1681             }
1682             break;
1683 
1684         case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
1685             if (value != EGL_TRUE && value != EGL_FALSE)
1686             {
1687                 val->setError(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
1688                 return false;
1689             }
1690             break;
1691 
1692         case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
1693             if (value != EGL_TRUE && value != EGL_FALSE)
1694             {
1695                 val->setError(EGL_BAD_ATTRIBUTE,
1696                               "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be "
1697                               "EGL_TRUE or EGL_FALSE.");
1698                 return false;
1699             }
1700             break;
1701 
1702         case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
1703             if (value != EGL_TRUE && value != EGL_FALSE)
1704             {
1705                 val->setError(EGL_BAD_ATTRIBUTE,
1706                               "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM "
1707                               "must be EGL_TRUE or EGL_FALSE.");
1708                 return false;
1709             }
1710             break;
1711 
1712         case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
1713             if (value != EGL_TRUE && value != EGL_FALSE)
1714             {
1715                 val->setError(EGL_BAD_ATTRIBUTE,
1716                               "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be "
1717                               "EGL_TRUE or EGL_FALSE.");
1718                 return false;
1719             }
1720             if (shareContext &&
1721                 shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE))
1722             {
1723                 val->setError(EGL_BAD_ATTRIBUTE,
1724                               "All contexts within a share group must be "
1725                               "created with the same value of "
1726                               "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.");
1727                 return false;
1728             }
1729             break;
1730 
1731         case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
1732             if (value != EGL_TRUE && value != EGL_FALSE)
1733             {
1734                 val->setError(EGL_BAD_ATTRIBUTE,
1735                               "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE must be "
1736                               "EGL_TRUE or EGL_FALSE.");
1737                 return false;
1738             }
1739             if (shareContext &&
1740                 shareContext->usingDisplaySemaphoreShareGroup() != (value == EGL_TRUE))
1741             {
1742                 val->setError(EGL_BAD_ATTRIBUTE,
1743                               "All contexts within a share group must be "
1744                               "created with the same value of "
1745                               "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE.");
1746                 return false;
1747             }
1748             break;
1749 
1750         case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
1751             if (value != EGL_TRUE && value != EGL_FALSE)
1752             {
1753                 val->setError(EGL_BAD_ATTRIBUTE,
1754                               "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must "
1755                               "be EGL_TRUE or EGL_FALSE.");
1756                 return false;
1757             }
1758             break;
1759 
1760         case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
1761             if (value != EGL_TRUE && value != EGL_FALSE)
1762             {
1763                 val->setError(EGL_BAD_ATTRIBUTE,
1764                               "EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE must "
1765                               "be EGL_TRUE or EGL_FALSE.");
1766                 return false;
1767             }
1768             break;
1769 
1770         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1771             if (value != EGL_TRUE && value != EGL_FALSE)
1772             {
1773                 val->setError(EGL_BAD_ATTRIBUTE,
1774                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1775                               "either EGL_TRUE or EGL_FALSE.");
1776                 return false;
1777             }
1778             break;
1779 
1780         case EGL_EXTENSIONS_ENABLED_ANGLE:
1781             if (value != EGL_TRUE && value != EGL_FALSE)
1782             {
1783                 val->setError(EGL_BAD_ATTRIBUTE,
1784                               "EGL_EXTENSIONS_ENABLED_ANGLE must be "
1785                               "either EGL_TRUE or EGL_FALSE.");
1786                 return false;
1787             }
1788             break;
1789 
1790         case EGL_POWER_PREFERENCE_ANGLE:
1791             if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
1792             {
1793                 val->setError(EGL_BAD_ATTRIBUTE,
1794                               "EGL_POWER_PREFERENCE_ANGLE must be "
1795                               "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
1796                 return false;
1797             }
1798             break;
1799 
1800         case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
1801             if (value != EGL_TRUE && value != EGL_FALSE)
1802             {
1803                 val->setError(EGL_BAD_ATTRIBUTE,
1804                               "EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE must be "
1805                               "either EGL_TRUE or EGL_FALSE.");
1806                 return false;
1807             }
1808             break;
1809 
1810         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
1811             switch (value)
1812             {
1813                 case EGL_CONTEXT_PRIORITY_LOW_IMG:
1814                 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1815                 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1816                     break;
1817                 default:
1818                     val->setError(EGL_BAD_ATTRIBUTE,
1819                                   "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG "
1820                                   "must be one of: EGL_CONTEXT_PRIORITY_LOW_IMG, "
1821                                   "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, or "
1822                                   "EGL_CONTEXT_PRIORITY_HIGH_IMG.");
1823                     return false;
1824             }
1825             break;
1826 
1827         case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
1828             if (value != EGL_TRUE && value != EGL_FALSE)
1829             {
1830                 val->setError(EGL_BAD_ATTRIBUTE,
1831                               "EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV must "
1832                               "be either EGL_TRUE or EGL_FALSE.");
1833                 return false;
1834             }
1835             break;
1836 
1837         case EGL_EXTERNAL_CONTEXT_ANGLE:
1838             if (value != EGL_TRUE && value != EGL_FALSE)
1839             {
1840                 val->setError(EGL_BAD_ATTRIBUTE,
1841                               "EGL_EXTERNAL_CONTEXT_ANGLE must "
1842                               "be either EGL_TRUE or EGL_FALSE.");
1843                 return false;
1844             }
1845             if (shareContext && (value == EGL_TRUE))
1846             {
1847                 val->setError(
1848                     EGL_BAD_ATTRIBUTE,
1849                     "EGL_EXTERNAL_CONTEXT_ANGLE doesn't allow creating with sharedContext.");
1850                 return false;
1851             }
1852             break;
1853         case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
1854             if (value != EGL_TRUE && value != EGL_FALSE)
1855             {
1856                 val->setError(EGL_BAD_ATTRIBUTE,
1857                               "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE must "
1858                               "be either EGL_TRUE or EGL_FALSE.");
1859                 return false;
1860             }
1861             break;
1862 
1863         case EGL_PROTECTED_CONTENT_EXT:
1864             if (value != EGL_TRUE && value != EGL_FALSE)
1865             {
1866                 val->setError(EGL_BAD_ATTRIBUTE,
1867                               "EGL_PROTECTED_CONTENT_EXT must "
1868                               "be either EGL_TRUE or EGL_FALSE.");
1869                 return false;
1870             }
1871             break;
1872 
1873         default:
1874             UNREACHABLE();
1875             return false;
1876     }
1877 
1878     return true;
1879 }
1880 
ValidateCreatePbufferSurfaceAttribute(const ValidationContext * val,const Display * display,EGLAttrib attribute)1881 bool ValidateCreatePbufferSurfaceAttribute(const ValidationContext *val,
1882                                            const Display *display,
1883                                            EGLAttrib attribute)
1884 {
1885     const DisplayExtensions &displayExtensions = display->getExtensions();
1886 
1887     switch (attribute)
1888     {
1889         case EGL_WIDTH:
1890         case EGL_HEIGHT:
1891         case EGL_LARGEST_PBUFFER:
1892         case EGL_TEXTURE_FORMAT:
1893         case EGL_TEXTURE_TARGET:
1894         case EGL_MIPMAP_TEXTURE:
1895         case EGL_VG_COLORSPACE:
1896         case EGL_GL_COLORSPACE:
1897         case EGL_VG_ALPHA_FORMAT:
1898             break;
1899 
1900         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1901             if (!displayExtensions.robustResourceInitializationANGLE)
1902             {
1903                 val->setError(EGL_BAD_ATTRIBUTE,
1904                               "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1905                               "requires EGL_ANGLE_robust_resource_initialization.");
1906                 return false;
1907             }
1908             break;
1909 
1910         case EGL_PROTECTED_CONTENT_EXT:
1911             if (!displayExtensions.protectedContentEXT)
1912             {
1913                 val->setError(EGL_BAD_ATTRIBUTE,
1914                               "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
1915                               "extension EGL_EXT_protected_content.");
1916                 return false;
1917             }
1918             break;
1919 
1920         default:
1921             val->setError(EGL_BAD_ATTRIBUTE);
1922             return false;
1923     }
1924 
1925     return true;
1926 }
1927 
ValidateCreatePbufferSurfaceAttributeValue(const ValidationContext * val,const Display * display,EGLAttrib attribute,EGLAttrib value)1928 bool ValidateCreatePbufferSurfaceAttributeValue(const ValidationContext *val,
1929                                                 const Display *display,
1930                                                 EGLAttrib attribute,
1931                                                 EGLAttrib value)
1932 {
1933     const DisplayExtensions &displayExtensions = display->getExtensions();
1934 
1935     switch (attribute)
1936     {
1937         case EGL_WIDTH:
1938         case EGL_HEIGHT:
1939             if (value < 0)
1940             {
1941                 val->setError(EGL_BAD_PARAMETER);
1942                 return false;
1943             }
1944             break;
1945 
1946         case EGL_LARGEST_PBUFFER:
1947             break;
1948 
1949         case EGL_TEXTURE_FORMAT:
1950             switch (value)
1951             {
1952                 case EGL_NO_TEXTURE:
1953                 case EGL_TEXTURE_RGB:
1954                 case EGL_TEXTURE_RGBA:
1955                     break;
1956                 default:
1957                     val->setError(EGL_BAD_ATTRIBUTE);
1958                     return false;
1959             }
1960             break;
1961 
1962         case EGL_TEXTURE_TARGET:
1963             switch (value)
1964             {
1965                 case EGL_NO_TEXTURE:
1966                 case EGL_TEXTURE_2D:
1967                     break;
1968                 default:
1969                     val->setError(EGL_BAD_ATTRIBUTE);
1970                     return false;
1971             }
1972             break;
1973 
1974         case EGL_MIPMAP_TEXTURE:
1975             break;
1976 
1977         case EGL_VG_COLORSPACE:
1978             break;
1979 
1980         case EGL_GL_COLORSPACE:
1981             ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
1982             break;
1983 
1984         case EGL_VG_ALPHA_FORMAT:
1985             break;
1986 
1987         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1988             ASSERT(displayExtensions.robustResourceInitializationANGLE);
1989             if (value != EGL_TRUE && value != EGL_FALSE)
1990             {
1991                 val->setError(EGL_BAD_ATTRIBUTE,
1992                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1993                               "either EGL_TRUE or EGL_FALSE.");
1994                 return false;
1995             }
1996             break;
1997 
1998         case EGL_PROTECTED_CONTENT_EXT:
1999             ASSERT(displayExtensions.protectedContentEXT);
2000             if (value != EGL_TRUE && value != EGL_FALSE)
2001             {
2002                 val->setError(EGL_BAD_ATTRIBUTE,
2003                               "EGL_PROTECTED_CONTENT_EXT must "
2004                               "be either EGL_TRUE or EGL_FALSE.");
2005                 return false;
2006             }
2007             break;
2008 
2009         default:
2010             UNREACHABLE();
2011             return false;
2012     }
2013 
2014     return true;
2015 }
2016 }  // anonymous namespace
2017 
setError(EGLint error) const2018 void ValidationContext::setError(EGLint error) const
2019 {
2020     eglThread->setError(error, entryPoint, labeledObject, nullptr);
2021 }
2022 
setError(EGLint error,const char * message...) const2023 void ValidationContext::setError(EGLint error, const char *message...) const
2024 {
2025     ASSERT(message);
2026 
2027     constexpr uint32_t kBufferSize = 1000;
2028     char buffer[kBufferSize];
2029 
2030     va_list args;
2031     va_start(args, message);
2032     vsnprintf(buffer, kBufferSize, message, args);
2033 
2034     eglThread->setError(error, entryPoint, labeledObject, buffer);
2035 }
2036 
ValidateDisplay(const ValidationContext * val,const Display * display)2037 bool ValidateDisplay(const ValidationContext *val, const Display *display)
2038 {
2039     ANGLE_VALIDATION_TRY(ValidateDisplayPointer(val, display));
2040 
2041     if (!display->isInitialized())
2042     {
2043         if (val)
2044         {
2045             val->setError(EGL_NOT_INITIALIZED, "display is not initialized.");
2046         }
2047         return false;
2048     }
2049 
2050     if (display->isDeviceLost())
2051     {
2052         if (val)
2053         {
2054             val->setError(EGL_CONTEXT_LOST, "display had a context loss");
2055         }
2056         return false;
2057     }
2058 
2059     return true;
2060 }
2061 
ValidateSurface(const ValidationContext * val,const Display * display,const Surface * surface)2062 bool ValidateSurface(const ValidationContext *val, const Display *display, const Surface *surface)
2063 {
2064     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2065 
2066     if (!display->isValidSurface(surface))
2067     {
2068         if (val)
2069         {
2070             val->setError(EGL_BAD_SURFACE);
2071         }
2072         return false;
2073     }
2074 
2075     return true;
2076 }
2077 
ValidateConfig(const ValidationContext * val,const Display * display,const Config * config)2078 bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config)
2079 {
2080     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2081 
2082     if (!display->isValidConfig(config))
2083     {
2084         if (val)
2085         {
2086             val->setError(EGL_BAD_CONFIG);
2087         }
2088         return false;
2089     }
2090 
2091     return true;
2092 }
2093 
ValidateContext(const ValidationContext * val,const Display * display,const gl::Context * context)2094 bool ValidateContext(const ValidationContext *val,
2095                      const Display *display,
2096                      const gl::Context *context)
2097 {
2098     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2099 
2100     if (!display->isValidContext(context))
2101     {
2102         if (val)
2103         {
2104             val->setError(EGL_BAD_CONTEXT);
2105         }
2106         return false;
2107     }
2108 
2109     return true;
2110 }
2111 
ValidateImage(const ValidationContext * val,const Display * display,const Image * image)2112 bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image)
2113 {
2114     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2115 
2116     if (!display->isValidImage(image))
2117     {
2118         if (val)
2119         {
2120             val->setError(EGL_BAD_PARAMETER, "image is not valid.");
2121         }
2122         return false;
2123     }
2124 
2125     return true;
2126 }
2127 
ValidateDevice(const ValidationContext * val,const Device * device)2128 bool ValidateDevice(const ValidationContext *val, const Device *device)
2129 {
2130     if (device == EGL_NO_DEVICE_EXT)
2131     {
2132         if (val)
2133         {
2134             val->setError(EGL_BAD_ACCESS, "device is EGL_NO_DEVICE.");
2135         }
2136         return false;
2137     }
2138 
2139     if (!Device::IsValidDevice(device))
2140     {
2141         if (val)
2142         {
2143             val->setError(EGL_BAD_ACCESS, "device is not valid.");
2144         }
2145         return false;
2146     }
2147 
2148     return true;
2149 }
2150 
ValidateSync(const ValidationContext * val,const Display * display,const Sync * sync)2151 bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync)
2152 {
2153     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2154 
2155     if (!display->isValidSync(sync))
2156     {
2157         if (val)
2158         {
2159             val->setError(EGL_BAD_PARAMETER, "sync object is not valid.");
2160         }
2161         return false;
2162     }
2163 
2164     return true;
2165 }
2166 
GetThreadIfValid(const Thread * thread)2167 const Thread *GetThreadIfValid(const Thread *thread)
2168 {
2169     // Threads should always be valid
2170     return thread;
2171 }
2172 
GetDisplayIfValid(const Display * display)2173 const Display *GetDisplayIfValid(const Display *display)
2174 {
2175     return ValidateDisplay(nullptr, display) ? display : nullptr;
2176 }
2177 
GetSurfaceIfValid(const Display * display,const Surface * surface)2178 const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface)
2179 {
2180     return ValidateSurface(nullptr, display, surface) ? surface : nullptr;
2181 }
2182 
GetImageIfValid(const Display * display,const Image * image)2183 const Image *GetImageIfValid(const Display *display, const Image *image)
2184 {
2185     return ValidateImage(nullptr, display, image) ? image : nullptr;
2186 }
2187 
GetStreamIfValid(const Display * display,const Stream * stream)2188 const Stream *GetStreamIfValid(const Display *display, const Stream *stream)
2189 {
2190     return ValidateStream(nullptr, display, stream) ? stream : nullptr;
2191 }
2192 
GetContextIfValid(const Display * display,const gl::Context * context)2193 const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context)
2194 {
2195     return ValidateContext(nullptr, display, context) ? context : nullptr;
2196 }
2197 
GetDeviceIfValid(const Device * device)2198 const Device *GetDeviceIfValid(const Device *device)
2199 {
2200     return ValidateDevice(nullptr, device) ? device : nullptr;
2201 }
2202 
GetSyncIfValid(const Display * display,const Sync * sync)2203 const Sync *GetSyncIfValid(const Display *display, const Sync *sync)
2204 {
2205     return ValidateSync(nullptr, display, sync) ? sync : nullptr;
2206 }
2207 
GetLabeledObjectIfValid(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object)2208 LabeledObject *GetLabeledObjectIfValid(Thread *thread,
2209                                        const Display *display,
2210                                        ObjectType objectType,
2211                                        EGLObjectKHR object)
2212 {
2213     if (objectType == ObjectType::Thread)
2214     {
2215         return thread;
2216     }
2217 
2218     LabeledObject *labeledObject = nullptr;
2219     if (ValidateLabeledObject(nullptr, display, objectType, object, &labeledObject))
2220     {
2221         return labeledObject;
2222     }
2223 
2224     return nullptr;
2225 }
2226 
ValidateInitialize(const ValidationContext * val,const Display * display,const EGLint * major,const EGLint * minor)2227 bool ValidateInitialize(const ValidationContext *val,
2228                         const Display *display,
2229                         const EGLint *major,
2230                         const EGLint *minor)
2231 {
2232     return ValidateDisplayPointer(val, display);
2233 }
2234 
ValidateTerminate(const ValidationContext * val,const Display * display)2235 bool ValidateTerminate(const ValidationContext *val, const Display *display)
2236 {
2237     return ValidateDisplayPointer(val, display);
2238 }
2239 
ValidateCreateContext(const ValidationContext * val,const Display * display,const Config * configuration,const gl::Context * shareContext,const AttributeMap & attributes)2240 bool ValidateCreateContext(const ValidationContext *val,
2241                            const Display *display,
2242                            const Config *configuration,
2243                            const gl::Context *shareContext,
2244                            const AttributeMap &attributes)
2245 {
2246     if (configuration)
2247     {
2248         ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
2249     }
2250     else
2251     {
2252         ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2253         const DisplayExtensions &displayExtensions = display->getExtensions();
2254         if (!displayExtensions.noConfigContext)
2255         {
2256             val->setError(EGL_BAD_CONFIG);
2257             return false;
2258         }
2259     }
2260 
2261     ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreateContextAttribute));
2262 
2263     for (const auto &attributePair : attributes)
2264     {
2265         EGLAttrib attribute = attributePair.first;
2266         EGLAttrib value     = attributePair.second;
2267         ANGLE_VALIDATION_TRY(
2268             ValidateCreateContextAttributeValue(val, display, shareContext, attribute, value));
2269     }
2270 
2271     // Get the requested client version (default is 1) and check it is 2 or 3.
2272     EGLAttrib clientMajorVersion = attributes.get(EGL_CONTEXT_CLIENT_VERSION, 1);
2273     EGLAttrib clientMinorVersion = attributes.get(EGL_CONTEXT_MINOR_VERSION, 0);
2274 
2275     switch (clientMajorVersion)
2276     {
2277         case 1:
2278             if (clientMinorVersion != 0 && clientMinorVersion != 1)
2279             {
2280                 val->setError(EGL_BAD_ATTRIBUTE);
2281                 return false;
2282             }
2283             if (configuration == EGL_NO_CONFIG_KHR)
2284             {
2285                 val->setError(EGL_BAD_MATCH);
2286                 return false;
2287             }
2288             if ((configuration != EGL_NO_CONFIG_KHR) &&
2289                 !(configuration->renderableType & EGL_OPENGL_ES_BIT))
2290             {
2291                 val->setError(EGL_BAD_MATCH);
2292                 return false;
2293             }
2294             break;
2295 
2296         case 2:
2297             if (clientMinorVersion != 0)
2298             {
2299                 val->setError(EGL_BAD_ATTRIBUTE);
2300                 return false;
2301             }
2302             if ((configuration != EGL_NO_CONFIG_KHR) &&
2303                 !(configuration->renderableType & EGL_OPENGL_ES2_BIT))
2304             {
2305                 val->setError(EGL_BAD_MATCH);
2306                 return false;
2307             }
2308             break;
2309         case 3:
2310             if (clientMinorVersion < 0 || clientMinorVersion > 2)
2311             {
2312                 val->setError(EGL_BAD_ATTRIBUTE);
2313                 return false;
2314             }
2315             if ((configuration != EGL_NO_CONFIG_KHR) &&
2316                 !(configuration->renderableType & EGL_OPENGL_ES3_BIT))
2317             {
2318                 val->setError(EGL_BAD_MATCH);
2319                 return false;
2320             }
2321             if (display->getMaxSupportedESVersion() <
2322                 gl::Version(static_cast<GLuint>(clientMajorVersion),
2323                             static_cast<GLuint>(clientMinorVersion)))
2324             {
2325                 gl::Version max = display->getMaxSupportedESVersion();
2326                 val->setError(EGL_BAD_ATTRIBUTE,
2327                               "Requested GLES version (%" PRIxPTR ".%" PRIxPTR
2328                               ") is greater than "
2329                               "max supported (%d, %d).",
2330                               clientMajorVersion, clientMinorVersion, max.major, max.minor);
2331                 return false;
2332             }
2333             break;
2334         default:
2335             val->setError(EGL_BAD_ATTRIBUTE);
2336             return false;
2337     }
2338 
2339     if (shareContext)
2340     {
2341         // Shared context is invalid or is owned by another display
2342         if (!display->isValidContext(shareContext))
2343         {
2344             val->setError(EGL_BAD_MATCH);
2345             return false;
2346         }
2347     }
2348 
2349     return true;
2350 }
2351 
ValidateCreateWindowSurface(const ValidationContext * val,const Display * display,const Config * config,EGLNativeWindowType window,const AttributeMap & attributes)2352 bool ValidateCreateWindowSurface(const ValidationContext *val,
2353                                  const Display *display,
2354                                  const Config *config,
2355                                  EGLNativeWindowType window,
2356                                  const AttributeMap &attributes)
2357 {
2358     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2359 
2360     if (!display->isValidNativeWindow(window))
2361     {
2362         val->setError(EGL_BAD_NATIVE_WINDOW);
2363         return false;
2364     }
2365 
2366     const DisplayExtensions &displayExtensions = display->getExtensions();
2367 
2368     attributes.initializeWithoutValidation();
2369 
2370     for (const auto &attributeIter : attributes)
2371     {
2372         EGLAttrib attribute = attributeIter.first;
2373         EGLAttrib value     = attributeIter.second;
2374 
2375         switch (attribute)
2376         {
2377             case EGL_RENDER_BUFFER:
2378                 switch (value)
2379                 {
2380                     case EGL_BACK_BUFFER:
2381                         break;
2382                     case EGL_SINGLE_BUFFER:
2383                         val->setError(EGL_BAD_MATCH);
2384                         return false;  // Rendering directly to front buffer not supported
2385                     default:
2386                         val->setError(EGL_BAD_ATTRIBUTE);
2387                         return false;
2388                 }
2389                 break;
2390 
2391             case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
2392                 if (!displayExtensions.postSubBuffer)
2393                 {
2394                     val->setError(EGL_BAD_ATTRIBUTE);
2395                     return false;
2396                 }
2397                 break;
2398 
2399             case EGL_WIDTH:
2400             case EGL_HEIGHT:
2401                 if (!displayExtensions.windowFixedSize)
2402                 {
2403                     val->setError(EGL_BAD_ATTRIBUTE);
2404                     return false;
2405                 }
2406                 if (value < 0)
2407                 {
2408                     val->setError(EGL_BAD_PARAMETER);
2409                     return false;
2410                 }
2411                 break;
2412 
2413             case EGL_FIXED_SIZE_ANGLE:
2414                 if (!displayExtensions.windowFixedSize)
2415                 {
2416                     val->setError(EGL_BAD_ATTRIBUTE);
2417                     return false;
2418                 }
2419                 break;
2420 
2421             case EGL_SURFACE_ORIENTATION_ANGLE:
2422                 if (!displayExtensions.surfaceOrientation)
2423                 {
2424                     val->setError(EGL_BAD_ATTRIBUTE,
2425                                   "EGL_ANGLE_surface_orientation is not enabled.");
2426                     return false;
2427                 }
2428                 break;
2429 
2430             case EGL_VG_COLORSPACE:
2431                 val->setError(EGL_BAD_MATCH);
2432                 return false;
2433 
2434             case EGL_GL_COLORSPACE:
2435                 ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2436                 break;
2437 
2438             case EGL_VG_ALPHA_FORMAT:
2439                 val->setError(EGL_BAD_MATCH);
2440                 return false;
2441 
2442             case EGL_DIRECT_COMPOSITION_ANGLE:
2443                 if (!displayExtensions.directComposition)
2444                 {
2445                     val->setError(EGL_BAD_ATTRIBUTE);
2446                     return false;
2447                 }
2448                 break;
2449 
2450             case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
2451                 if (!display->getExtensions().robustResourceInitializationANGLE)
2452                 {
2453                     val->setError(EGL_BAD_ATTRIBUTE,
2454                                   "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
2455                                   "requires EGL_ANGLE_robust_resource_initialization.");
2456                     return false;
2457                 }
2458                 if (value != EGL_TRUE && value != EGL_FALSE)
2459                 {
2460                     val->setError(EGL_BAD_ATTRIBUTE,
2461                                   "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
2462                                   "either EGL_TRUE or EGL_FALSE.");
2463                     return false;
2464                 }
2465                 break;
2466 
2467             case EGL_GGP_STREAM_DESCRIPTOR_ANGLE:
2468                 if (!display->getExtensions().ggpStreamDescriptor)
2469                 {
2470                     val->setError(EGL_BAD_ATTRIBUTE,
2471                                   "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires "
2472                                   "EGL_ANGLE_ggp_stream_descriptor.");
2473                     return false;
2474                 }
2475                 break;
2476 
2477             case EGL_PROTECTED_CONTENT_EXT:
2478                 if (!displayExtensions.protectedContentEXT)
2479                 {
2480                     val->setError(EGL_BAD_ATTRIBUTE,
2481                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
2482                                   "extension EGL_EXT_protected_content.");
2483                     return false;
2484                 }
2485                 if (value != EGL_TRUE && value != EGL_FALSE)
2486                 {
2487                     val->setError(EGL_BAD_ATTRIBUTE,
2488                                   "EGL_PROTECTED_CONTENT_EXT must "
2489                                   "be either EGL_TRUE or EGL_FALSE.");
2490                     return false;
2491                 }
2492                 break;
2493 
2494             case EGL_SWAP_INTERVAL_ANGLE:
2495                 if (!displayExtensions.createSurfaceSwapIntervalANGLE)
2496                 {
2497                     val->setError(EGL_BAD_ATTRIBUTE,
2498                                   "Attribute EGL_SWAP_INTERVAL_ANGLE requires "
2499                                   "extension EGL_ANGLE_create_surface_swap_interval.");
2500                     return false;
2501                 }
2502                 if (value < config->minSwapInterval || value > config->maxSwapInterval)
2503                 {
2504                     val->setError(EGL_BAD_ATTRIBUTE,
2505                                   "EGL_SWAP_INTERVAL_ANGLE must "
2506                                   "be within the EGLConfig min and max swap intervals.");
2507                     return false;
2508                 }
2509                 break;
2510 
2511             default:
2512                 val->setError(EGL_BAD_ATTRIBUTE);
2513                 return false;
2514         }
2515     }
2516 
2517     if ((config->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) != 0 &&
2518         !displayExtensions.mutableRenderBufferKHR)
2519     {
2520         val->setError(EGL_BAD_ATTRIBUTE,
2521                       "EGL_MUTABLE_RENDER_BUFFER_BIT_KHR requires EGL_KHR_mutable_render_buffer.");
2522         return false;
2523     }
2524 
2525     if (Display::hasExistingWindowSurface(window))
2526     {
2527         val->setError(EGL_BAD_ALLOC);
2528         return false;
2529     }
2530 
2531     return true;
2532 }
2533 
ValidateCreatePbufferSurface(const ValidationContext * val,const Display * display,const Config * config,const AttributeMap & attributes)2534 bool ValidateCreatePbufferSurface(const ValidationContext *val,
2535                                   const Display *display,
2536                                   const Config *config,
2537                                   const AttributeMap &attributes)
2538 {
2539     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2540     ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreatePbufferSurfaceAttribute));
2541 
2542     for (const auto &attributeIter : attributes)
2543     {
2544         EGLAttrib attribute = attributeIter.first;
2545         EGLAttrib value     = attributeIter.second;
2546 
2547         ANGLE_VALIDATION_TRY(
2548             ValidateCreatePbufferSurfaceAttributeValue(val, display, attribute, value));
2549     }
2550 
2551     if ((config->surfaceType & EGL_PBUFFER_BIT) == 0)
2552     {
2553         val->setError(EGL_BAD_MATCH);
2554         return false;
2555     }
2556 
2557     const Caps &caps = display->getCaps();
2558 
2559     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
2560     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
2561 
2562     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
2563         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
2564     {
2565         val->setError(EGL_BAD_MATCH);
2566         return false;
2567     }
2568 
2569     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
2570         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
2571     {
2572         val->setError(EGL_BAD_ATTRIBUTE);
2573         return false;
2574     }
2575 
2576     EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
2577     EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
2578     if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
2579         (!gl::isPow2(width) || !gl::isPow2(height)))
2580     {
2581         val->setError(EGL_BAD_MATCH);
2582         return false;
2583     }
2584 
2585     return true;
2586 }
2587 
ValidateCreatePbufferFromClientBuffer(const ValidationContext * val,const Display * display,EGLenum buftype,EGLClientBuffer buffer,const Config * config,const AttributeMap & attributes)2588 bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
2589                                            const Display *display,
2590                                            EGLenum buftype,
2591                                            EGLClientBuffer buffer,
2592                                            const Config *config,
2593                                            const AttributeMap &attributes)
2594 {
2595     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2596 
2597     const DisplayExtensions &displayExtensions = display->getExtensions();
2598 
2599     attributes.initializeWithoutValidation();
2600 
2601     switch (buftype)
2602     {
2603         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
2604             if (!displayExtensions.d3dShareHandleClientBuffer)
2605             {
2606                 val->setError(EGL_BAD_PARAMETER);
2607                 return false;
2608             }
2609             if (buffer == nullptr)
2610             {
2611                 val->setError(EGL_BAD_PARAMETER);
2612                 return false;
2613             }
2614             break;
2615 
2616         case EGL_D3D_TEXTURE_ANGLE:
2617             if (!displayExtensions.d3dTextureClientBuffer)
2618             {
2619                 val->setError(EGL_BAD_PARAMETER);
2620                 return false;
2621             }
2622             if (buffer == nullptr)
2623             {
2624                 val->setError(EGL_BAD_PARAMETER);
2625                 return false;
2626             }
2627             break;
2628 
2629         case EGL_IOSURFACE_ANGLE:
2630             if (!displayExtensions.iosurfaceClientBuffer)
2631             {
2632                 val->setError(EGL_BAD_PARAMETER,
2633                               "<buftype> EGL_IOSURFACE_ANGLE requires the "
2634                               "EGL_ANGLE_iosurface_client_buffer extension.");
2635                 return false;
2636             }
2637             if (buffer == nullptr)
2638             {
2639                 val->setError(EGL_BAD_PARAMETER, "<buffer> must be non null");
2640                 return false;
2641             }
2642             break;
2643         case EGL_EXTERNAL_SURFACE_ANGLE:
2644             if (!display->getExtensions().externalContextAndSurface)
2645             {
2646                 val->setError(EGL_BAD_ATTRIBUTE,
2647                               "Attribute "
2648                               "EGL_EXTERNAL_SURFACE_ANGLE requires "
2649                               "EGL_ANGLE_external_context_and_surface.");
2650                 return false;
2651             }
2652             if (buffer != nullptr)
2653             {
2654                 val->setError(EGL_BAD_PARAMETER, "<buffer> must be null");
2655                 return false;
2656             }
2657             break;
2658 
2659         default:
2660             val->setError(EGL_BAD_PARAMETER);
2661             return false;
2662     }
2663 
2664     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2665          attributeIter != attributes.end(); attributeIter++)
2666     {
2667         EGLAttrib attribute = attributeIter->first;
2668         EGLAttrib value     = attributeIter->second;
2669 
2670         switch (attribute)
2671         {
2672             case EGL_WIDTH:
2673             case EGL_HEIGHT:
2674                 if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
2675                     buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE &&
2676                     buftype != EGL_EXTERNAL_SURFACE_ANGLE)
2677                 {
2678                     val->setError(EGL_BAD_PARAMETER,
2679                                   "Width and Height are not supported for this <buftype>");
2680                     return false;
2681                 }
2682                 if (value < 0)
2683                 {
2684                     val->setError(EGL_BAD_PARAMETER, "Width and Height must be positive");
2685                     return false;
2686                 }
2687                 break;
2688 
2689             case EGL_TEXTURE_FORMAT:
2690                 switch (value)
2691                 {
2692                     case EGL_NO_TEXTURE:
2693                     case EGL_TEXTURE_RGB:
2694                     case EGL_TEXTURE_RGBA:
2695                         break;
2696                     default:
2697                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_FORMAT");
2698                         return false;
2699                 }
2700                 break;
2701 
2702             case EGL_TEXTURE_TARGET:
2703                 switch (value)
2704                 {
2705                     case EGL_NO_TEXTURE:
2706                     case EGL_TEXTURE_2D:
2707                         break;
2708                     case EGL_TEXTURE_RECTANGLE_ANGLE:
2709                         if (buftype != EGL_IOSURFACE_ANGLE)
2710                         {
2711                             val->setError(EGL_BAD_PARAMETER,
2712                                           "<buftype> doesn't support rectangle texture targets");
2713                             return false;
2714                         }
2715                         break;
2716 
2717                     default:
2718                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_TARGET");
2719                         return false;
2720                 }
2721                 break;
2722 
2723             case EGL_MIPMAP_TEXTURE:
2724                 break;
2725 
2726             case EGL_IOSURFACE_PLANE_ANGLE:
2727                 if (buftype != EGL_IOSURFACE_ANGLE)
2728                 {
2729                     val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support iosurface plane");
2730                     return false;
2731                 }
2732                 break;
2733 
2734             case EGL_TEXTURE_TYPE_ANGLE:
2735                 if (buftype != EGL_IOSURFACE_ANGLE)
2736                 {
2737                     val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support texture type");
2738                     return false;
2739                 }
2740                 break;
2741 
2742             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
2743                 if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
2744                 {
2745                     val->setError(EGL_BAD_ATTRIBUTE,
2746                                   "<buftype> doesn't support texture internal format");
2747                     return false;
2748                 }
2749                 break;
2750 
2751             case EGL_GL_COLORSPACE:
2752                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
2753                 {
2754                     val->setError(EGL_BAD_ATTRIBUTE,
2755                                   "<buftype> doesn't support setting GL colorspace");
2756                     return false;
2757                 }
2758                 break;
2759 
2760             case EGL_IOSURFACE_USAGE_HINT_ANGLE:
2761                 if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
2762                 {
2763                     val->setError(EGL_BAD_ATTRIBUTE,
2764                                   "IOSurface usage hint must only contain READ or WRITE");
2765                     return false;
2766                 }
2767                 break;
2768 
2769             case EGL_TEXTURE_OFFSET_X_ANGLE:
2770             case EGL_TEXTURE_OFFSET_Y_ANGLE:
2771                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
2772                 {
2773                     val->setError(EGL_BAD_ATTRIBUTE,
2774                                   "<buftype> doesn't support setting texture offset");
2775                     return false;
2776                 }
2777                 if (value < 0)
2778                 {
2779                     val->setError(EGL_BAD_ATTRIBUTE, "Texture offset cannot be negative");
2780                     return false;
2781                 }
2782                 break;
2783 
2784             case EGL_PROTECTED_CONTENT_EXT:
2785                 if (!displayExtensions.protectedContentEXT)
2786                 {
2787                     val->setError(EGL_BAD_ATTRIBUTE,
2788                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
2789                                   "extension EGL_EXT_protected_content.");
2790                     return false;
2791                 }
2792                 if (value != EGL_TRUE && value != EGL_FALSE)
2793                 {
2794                     val->setError(EGL_BAD_ATTRIBUTE,
2795                                   "EGL_PROTECTED_CONTENT_EXT must "
2796                                   "be either EGL_TRUE or EGL_FALSE.");
2797                     return false;
2798                 }
2799                 break;
2800 
2801             default:
2802                 val->setError(EGL_BAD_ATTRIBUTE);
2803                 return false;
2804         }
2805     }
2806 
2807     EGLAttrib colorspace = attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
2808     if (colorspace != EGL_GL_COLORSPACE_LINEAR && colorspace != EGL_GL_COLORSPACE_SRGB)
2809     {
2810         val->setError(EGL_BAD_ATTRIBUTE, "invalid GL colorspace");
2811         return false;
2812     }
2813 
2814     if (!(config->surfaceType & EGL_PBUFFER_BIT))
2815     {
2816         val->setError(EGL_BAD_MATCH);
2817         return false;
2818     }
2819 
2820     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
2821     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
2822     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
2823         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
2824     {
2825         val->setError(EGL_BAD_MATCH);
2826         return false;
2827     }
2828     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
2829         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
2830     {
2831         // TODO(cwallez@chromium.org): For IOSurface pbuffers we require that EGL_TEXTURE_RGBA is
2832         // set so that eglBindTexImage works. Normally this is only allowed if the config exposes
2833         // the bindToTextureRGB/RGBA flag. This issue is that enabling this flags means that
2834         // eglBindTexImage should also work for regular pbuffers which isn't implemented on macOS.
2835         // Instead of adding the flag we special case the check here to be ignored for IOSurfaces.
2836         // The TODO is to find a proper solution for this, maybe by implementing eglBindTexImage on
2837         // OSX?
2838         if (buftype != EGL_IOSURFACE_ANGLE)
2839         {
2840             val->setError(EGL_BAD_ATTRIBUTE);
2841             return false;
2842         }
2843     }
2844 
2845     if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
2846     {
2847         EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
2848         EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
2849 
2850         if (width == 0 || height == 0)
2851         {
2852             val->setError(EGL_BAD_ATTRIBUTE);
2853             return false;
2854         }
2855 
2856         const Caps &caps = display->getCaps();
2857         if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
2858             (!gl::isPow2(width) || !gl::isPow2(height)))
2859         {
2860             val->setError(EGL_BAD_MATCH);
2861             return false;
2862         }
2863     }
2864 
2865     if (buftype == EGL_IOSURFACE_ANGLE)
2866     {
2867         if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
2868         {
2869             val->setError(EGL_BAD_ATTRIBUTE,
2870                           "EGL_IOSURFACE requires the texture target to match the config");
2871             return false;
2872         }
2873         if (textureFormat != EGL_TEXTURE_RGBA)
2874         {
2875             val->setError(EGL_BAD_ATTRIBUTE, "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format");
2876             return false;
2877         }
2878 
2879         if (!attributes.contains(EGL_WIDTH) || !attributes.contains(EGL_HEIGHT) ||
2880             !attributes.contains(EGL_TEXTURE_FORMAT) ||
2881             !attributes.contains(EGL_TEXTURE_TYPE_ANGLE) ||
2882             !attributes.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE) ||
2883             !attributes.contains(EGL_IOSURFACE_PLANE_ANGLE))
2884         {
2885             val->setError(EGL_BAD_PARAMETER, "Missing required attribute for EGL_IOSURFACE");
2886             return false;
2887         }
2888     }
2889 
2890     ANGLE_EGL_TRY_RETURN(val->eglThread,
2891                          display->validateClientBuffer(config, buftype, buffer, attributes),
2892                          val->entryPoint, val->labeledObject, false);
2893 
2894     return true;
2895 }
2896 
ValidateCreatePixmapSurface(const ValidationContext * val,const Display * display,const Config * config,EGLNativePixmapType pixmap,const AttributeMap & attributes)2897 bool ValidateCreatePixmapSurface(const ValidationContext *val,
2898                                  const Display *display,
2899                                  const Config *config,
2900                                  EGLNativePixmapType pixmap,
2901                                  const AttributeMap &attributes)
2902 {
2903     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2904 
2905     const DisplayExtensions &displayExtensions = display->getExtensions();
2906 
2907     attributes.initializeWithoutValidation();
2908 
2909     for (const auto &attributePair : attributes)
2910     {
2911         EGLAttrib attribute = attributePair.first;
2912         EGLAttrib value     = attributePair.second;
2913 
2914         switch (attribute)
2915         {
2916             case EGL_GL_COLORSPACE:
2917                 ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2918                 break;
2919 
2920             case EGL_VG_COLORSPACE:
2921                 break;
2922             case EGL_VG_ALPHA_FORMAT:
2923                 break;
2924 
2925             case EGL_TEXTURE_FORMAT:
2926                 if (!displayExtensions.textureFromPixmapNOK)
2927                 {
2928                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
2929                     return false;
2930                 }
2931                 switch (value)
2932                 {
2933                     case EGL_NO_TEXTURE:
2934                     case EGL_TEXTURE_RGB:
2935                     case EGL_TEXTURE_RGBA:
2936                         break;
2937                     default:
2938                         val->setError(EGL_BAD_ATTRIBUTE);
2939                         return false;
2940                 }
2941                 break;
2942 
2943             case EGL_TEXTURE_TARGET:
2944                 if (!displayExtensions.textureFromPixmapNOK)
2945                 {
2946                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
2947                     return false;
2948                 }
2949                 switch (value)
2950                 {
2951                     case EGL_NO_TEXTURE:
2952                     case EGL_TEXTURE_2D:
2953                         break;
2954                     default:
2955                         val->setError(EGL_BAD_ATTRIBUTE);
2956                         return false;
2957                 }
2958                 break;
2959 
2960             case EGL_MIPMAP_TEXTURE:
2961                 if (!displayExtensions.textureFromPixmapNOK)
2962                 {
2963                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
2964                     return false;
2965                 }
2966                 break;
2967 
2968             case EGL_PROTECTED_CONTENT_EXT:
2969                 if (!displayExtensions.protectedContentEXT)
2970                 {
2971                     val->setError(EGL_BAD_ATTRIBUTE,
2972                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
2973                                   "extension EGL_EXT_protected_content.");
2974                     return false;
2975                 }
2976                 if (value != EGL_TRUE && value != EGL_FALSE)
2977                 {
2978                     val->setError(EGL_BAD_ATTRIBUTE,
2979                                   "EGL_PROTECTED_CONTENT_EXT must "
2980                                   "be either EGL_TRUE or EGL_FALSE.");
2981                     return false;
2982                 }
2983                 break;
2984 
2985             default:
2986                 val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR, attribute);
2987                 return false;
2988         }
2989     }
2990 
2991     if (!(config->surfaceType & EGL_PIXMAP_BIT))
2992     {
2993         val->setError(EGL_BAD_MATCH, "Congfig does not suport pixmaps.");
2994         return false;
2995     }
2996 
2997     ANGLE_EGL_TRY_RETURN(val->eglThread, display->valdiatePixmap(config, pixmap, attributes),
2998                          val->entryPoint, val->labeledObject, false);
2999 
3000     return true;
3001 }
3002 
ValidateMakeCurrent(const ValidationContext * val,const Display * display,const Surface * draw,const Surface * read,const gl::Context * context)3003 bool ValidateMakeCurrent(const ValidationContext *val,
3004                          const Display *display,
3005                          const Surface *draw,
3006                          const Surface *read,
3007                          const gl::Context *context)
3008 {
3009     if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
3010     {
3011         val->setError(EGL_BAD_MATCH, "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE");
3012         return false;
3013     }
3014 
3015     // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
3016     // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
3017     if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
3018     {
3019         if (display->getExtensions().surfacelessContext)
3020         {
3021             if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
3022             {
3023                 val->setError(EGL_BAD_MATCH,
3024                               "If ctx is not EGL_NOT_CONTEXT, draw or read must "
3025                               "both be EGL_NO_SURFACE, or both not");
3026                 return false;
3027             }
3028         }
3029         else
3030         {
3031             val->setError(EGL_BAD_MATCH,
3032                           "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE");
3033             return false;
3034         }
3035     }
3036 
3037     // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
3038     // EGL_BAD_MATCH error is generated.
3039     if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
3040     {
3041         val->setError(EGL_BAD_MATCH,
3042                       "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE");
3043         return false;
3044     }
3045 
3046     if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
3047     {
3048         val->setError(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle");
3049         return false;
3050     }
3051 
3052     // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
3053     if (!display->isInitialized() &&
3054         (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
3055     {
3056         val->setError(EGL_NOT_INITIALIZED, "'dpy' not initialized");
3057         return false;
3058     }
3059 
3060     if (context != EGL_NO_CONTEXT)
3061     {
3062         ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3063     }
3064 
3065     if (display->isInitialized() && display->isDeviceLost())
3066     {
3067         val->setError(EGL_CONTEXT_LOST);
3068         return false;
3069     }
3070 
3071     if (draw != EGL_NO_SURFACE)
3072     {
3073         ANGLE_VALIDATION_TRY(ValidateSurface(val, display, draw));
3074     }
3075 
3076     if (read != EGL_NO_SURFACE)
3077     {
3078         ANGLE_VALIDATION_TRY(ValidateSurface(val, display, read));
3079         ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
3080     }
3081 
3082     if (draw != read)
3083     {
3084         if (draw)
3085         {
3086             ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, draw));
3087         }
3088         if (read)
3089         {
3090             ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
3091         }
3092     }
3093     return true;
3094 }
3095 
ValidateCreateImage(const ValidationContext * val,const Display * display,const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)3096 bool ValidateCreateImage(const ValidationContext *val,
3097                          const Display *display,
3098                          const gl::Context *context,
3099                          EGLenum target,
3100                          EGLClientBuffer buffer,
3101                          const AttributeMap &attributes)
3102 {
3103 
3104     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3105 
3106     attributes.initializeWithoutValidation();
3107 
3108     const DisplayExtensions &displayExtensions = display->getExtensions();
3109 
3110     // TODO(geofflang): Complete validation from EGL_KHR_image_base:
3111     // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
3112     // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
3113 
3114     for (AttributeMap::const_iterator attributeIter = attributes.begin();
3115          attributeIter != attributes.end(); attributeIter++)
3116     {
3117         EGLAttrib attribute = attributeIter->first;
3118         EGLAttrib value     = attributeIter->second;
3119 
3120         switch (attribute)
3121         {
3122             case EGL_IMAGE_PRESERVED:
3123                 switch (value)
3124                 {
3125                     case EGL_TRUE:
3126                     case EGL_FALSE:
3127                         break;
3128 
3129                     default:
3130                         val->setError(EGL_BAD_PARAMETER,
3131                                       "EGL_IMAGE_PRESERVED must be EGL_TRUE or EGL_FALSE.");
3132                         return false;
3133                 }
3134                 break;
3135 
3136             case EGL_GL_TEXTURE_LEVEL:
3137                 if (!displayExtensions.glTexture2DImage &&
3138                     !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
3139                 {
3140                     val->setError(EGL_BAD_PARAMETER,
3141                                   "EGL_GL_TEXTURE_LEVEL cannot be used "
3142                                   "without KHR_gl_texture_*_image support.");
3143                     return false;
3144                 }
3145 
3146                 if (value < 0)
3147                 {
3148                     val->setError(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL cannot be negative.");
3149                     return false;
3150                 }
3151                 break;
3152 
3153             case EGL_GL_TEXTURE_ZOFFSET:
3154                 if (!displayExtensions.glTexture3DImage)
3155                 {
3156                     val->setError(EGL_BAD_PARAMETER,
3157                                   "EGL_GL_TEXTURE_ZOFFSET cannot be used "
3158                                   "without KHR_gl_texture_3D_image support.");
3159                     return false;
3160                 }
3161                 break;
3162 
3163             case EGL_GL_COLORSPACE:
3164                 if (!displayExtensions.glColorspace)
3165                 {
3166                     val->setError(EGL_BAD_PARAMETER,
3167                                   "EGL_GL_COLORSPACE cannot be used "
3168                                   "without EGL_KHR_gl_colorspace support.");
3169                     return false;
3170                 }
3171                 switch (value)
3172                 {
3173                     case EGL_GL_COLORSPACE_DEFAULT_EXT:
3174                         break;
3175                     default:
3176                         ANGLE_VALIDATION_TRY(
3177                             ValidateColorspaceAttribute(val, displayExtensions, value));
3178                         break;
3179                 }
3180                 break;
3181 
3182             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
3183                 if (!displayExtensions.imageD3D11Texture)
3184                 {
3185                     val->setError(
3186                         EGL_BAD_PARAMETER,
3187                         "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE and EGL_TEXTURE_TYPE_ANGLE cannot "
3188                         "be used without EGL_ANGLE_image_d3d11_texture support.");
3189                     return false;
3190                 }
3191                 break;
3192 
3193             case EGL_D3D11_TEXTURE_PLANE_ANGLE:
3194                 if (!displayExtensions.imageD3D11Texture)
3195                 {
3196                     val->setError(EGL_BAD_ATTRIBUTE,
3197                                   "EGL_D3D11_TEXTURE_PLANE_ANGLE cannot be used without "
3198                                   "EGL_ANGLE_image_d3d11_texture support.");
3199                     return false;
3200                 }
3201                 break;
3202 
3203             case EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE:
3204                 if (!displayExtensions.imageD3D11Texture)
3205                 {
3206                     val->setError(EGL_BAD_ATTRIBUTE,
3207                                   "EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE cannot be used without "
3208                                   "EGL_ANGLE_image_d3d11_texture support.");
3209                     return false;
3210                 }
3211                 break;
3212 
3213             case EGL_WIDTH:
3214             case EGL_HEIGHT:
3215                 if (target != EGL_LINUX_DMA_BUF_EXT)
3216                 {
3217                     val->setError(
3218                         EGL_BAD_PARAMETER,
3219                         "Parameter cannot be used if target is not EGL_LINUX_DMA_BUF_EXT");
3220                     return false;
3221                 }
3222                 break;
3223 
3224             case EGL_LINUX_DRM_FOURCC_EXT:
3225             case EGL_DMA_BUF_PLANE0_FD_EXT:
3226             case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
3227             case EGL_DMA_BUF_PLANE0_PITCH_EXT:
3228             case EGL_DMA_BUF_PLANE1_FD_EXT:
3229             case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
3230             case EGL_DMA_BUF_PLANE1_PITCH_EXT:
3231             case EGL_DMA_BUF_PLANE2_FD_EXT:
3232             case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
3233             case EGL_DMA_BUF_PLANE2_PITCH_EXT:
3234                 if (!displayExtensions.imageDmaBufImportEXT)
3235                 {
3236                     val->setError(EGL_BAD_PARAMETER,
3237                                   "Parameter cannot be used without "
3238                                   "EGL_EXT_image_dma_buf_import support.");
3239                     return false;
3240                 }
3241                 break;
3242 
3243             case EGL_YUV_COLOR_SPACE_HINT_EXT:
3244                 if (!displayExtensions.imageDmaBufImportEXT)
3245                 {
3246                     val->setError(EGL_BAD_PARAMETER,
3247                                   "Parameter cannot be used without "
3248                                   "EGL_EXT_image_dma_buf_import support.");
3249                     return false;
3250                 }
3251 
3252                 switch (value)
3253                 {
3254                     case EGL_ITU_REC601_EXT:
3255                     case EGL_ITU_REC709_EXT:
3256                     case EGL_ITU_REC2020_EXT:
3257                         break;
3258 
3259                     default:
3260                         val->setError(EGL_BAD_PARAMETER,
3261                                       "Invalid value for EGL_YUV_COLOR_SPACE_HINT_EXT.");
3262                         return false;
3263                 }
3264                 break;
3265 
3266             case EGL_SAMPLE_RANGE_HINT_EXT:
3267                 if (!displayExtensions.imageDmaBufImportEXT)
3268                 {
3269                     val->setError(EGL_BAD_PARAMETER,
3270                                   "Parameter cannot be used without "
3271                                   "EGL_EXT_image_dma_buf_import support.");
3272                     return false;
3273                 }
3274 
3275                 switch (value)
3276                 {
3277                     case EGL_YUV_FULL_RANGE_EXT:
3278                     case EGL_YUV_NARROW_RANGE_EXT:
3279                         break;
3280 
3281                     default:
3282                         val->setError(EGL_BAD_PARAMETER,
3283                                       "Invalid value for EGL_SAMPLE_RANGE_HINT_EXT.");
3284                         return false;
3285                 }
3286                 break;
3287 
3288             case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
3289             case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
3290                 if (!displayExtensions.imageDmaBufImportEXT)
3291                 {
3292                     val->setError(EGL_BAD_PARAMETER,
3293                                   "Parameter cannot be used without "
3294                                   "EGL_EXT_image_dma_buf_import support.");
3295                     return false;
3296                 }
3297 
3298                 switch (value)
3299                 {
3300                     case EGL_YUV_CHROMA_SITING_0_EXT:
3301                     case EGL_YUV_CHROMA_SITING_0_5_EXT:
3302                         break;
3303 
3304                     default:
3305                         val->setError(
3306                             EGL_BAD_PARAMETER,
3307                             "Invalid value for EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT or "
3308                             "EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT.");
3309                         return false;
3310                 }
3311                 break;
3312 
3313             case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
3314             case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
3315             case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
3316             case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
3317             case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
3318             case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
3319             case EGL_DMA_BUF_PLANE3_FD_EXT:
3320             case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
3321             case EGL_DMA_BUF_PLANE3_PITCH_EXT:
3322             case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
3323             case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
3324                 if (!displayExtensions.imageDmaBufImportModifiersEXT)
3325                 {
3326                     val->setError(EGL_BAD_PARAMETER,
3327                                   "Parameter cannot be used without "
3328                                   "EGL_EXT_image_dma_buf_import_modifiers support.");
3329                     return false;
3330                 }
3331                 break;
3332 
3333             case EGL_PROTECTED_CONTENT_EXT:
3334                 if (!displayExtensions.protectedContentEXT)
3335                 {
3336                     val->setError(EGL_BAD_ATTRIBUTE,
3337                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
3338                                   "extension EGL_EXT_protected_content.");
3339                     return false;
3340                 }
3341                 if (value != EGL_TRUE && value != EGL_FALSE)
3342                 {
3343                     val->setError(EGL_BAD_ATTRIBUTE,
3344                                   "EGL_PROTECTED_CONTENT_EXT must "
3345                                   "be either EGL_TRUE or EGL_FALSE.");
3346                     return false;
3347                 }
3348                 break;
3349 
3350             default:
3351                 val->setError(EGL_BAD_PARAMETER, "invalid attribute: 0x%04" PRIxPTR "X", attribute);
3352                 return false;
3353         }
3354     }
3355 
3356     switch (target)
3357     {
3358         case EGL_GL_TEXTURE_2D:
3359         {
3360             if (!displayExtensions.glTexture2DImage)
3361             {
3362                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
3363                 return false;
3364             }
3365 
3366             if (buffer == 0)
3367             {
3368                 val->setError(EGL_BAD_PARAMETER,
3369                               "buffer cannot reference a 2D texture with the name 0.");
3370                 return false;
3371             }
3372 
3373             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3374             const gl::Texture *texture =
3375                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3376             if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
3377             {
3378                 val->setError(EGL_BAD_PARAMETER, "target is not a 2D texture.");
3379                 return false;
3380             }
3381 
3382             if (texture->getBoundSurface() != nullptr)
3383             {
3384                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3385                 return false;
3386             }
3387 
3388             EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3389             if (texture->getWidth(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0 ||
3390                 texture->getHeight(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0)
3391             {
3392                 val->setError(EGL_BAD_PARAMETER,
3393                               "target 2D texture does not have a valid size at specified level.");
3394                 return false;
3395             }
3396 
3397             bool protectedContentAttrib =
3398                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3399             if (protectedContentAttrib != texture->hasProtectedContent())
3400             {
3401                 val->setError(EGL_BAD_PARAMETER,
3402                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3403                               "of target.");
3404                 return false;
3405             }
3406 
3407             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3408         }
3409         break;
3410 
3411         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3412         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3413         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3414         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3415         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3416         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3417         {
3418             if (!displayExtensions.glTextureCubemapImage)
3419             {
3420                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
3421                 return false;
3422             }
3423 
3424             if (buffer == 0)
3425             {
3426                 val->setError(EGL_BAD_PARAMETER,
3427                               "buffer cannot reference a cubemap texture with the name 0.");
3428                 return false;
3429             }
3430 
3431             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3432             const gl::Texture *texture =
3433                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3434             if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
3435             {
3436                 val->setError(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
3437                 return false;
3438             }
3439 
3440             if (texture->getBoundSurface() != nullptr)
3441             {
3442                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3443                 return false;
3444             }
3445 
3446             EGLAttrib level               = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3447             gl::TextureTarget cubeMapFace = egl_gl::EGLCubeMapTargetToCubeMapTarget(target);
3448             if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
3449                 texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
3450             {
3451                 val->setError(EGL_BAD_PARAMETER,
3452                               "target cubemap texture does not have a valid "
3453                               "size at specified level and face.");
3454                 return false;
3455             }
3456 
3457             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3458 
3459             if (level == 0 && !texture->isMipmapComplete() &&
3460                 CubeTextureHasUnspecifiedLevel0Face(texture))
3461             {
3462                 val->setError(EGL_BAD_PARAMETER,
3463                               "if level is zero and the texture is incomplete, "
3464                               "it must have all of its faces specified at level "
3465                               "zero.");
3466                 return false;
3467             }
3468 
3469             bool protectedContentAttrib =
3470                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3471             if (protectedContentAttrib != texture->hasProtectedContent())
3472             {
3473                 val->setError(EGL_BAD_PARAMETER,
3474                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3475                               "of target.");
3476                 return false;
3477             }
3478         }
3479         break;
3480 
3481         case EGL_GL_TEXTURE_3D:
3482         {
3483             if (!displayExtensions.glTexture3DImage)
3484             {
3485                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
3486                 return false;
3487             }
3488 
3489             if (buffer == 0)
3490             {
3491                 val->setError(EGL_BAD_PARAMETER,
3492                               "buffer cannot reference a 3D texture with the name 0.");
3493                 return false;
3494             }
3495 
3496             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3497             const gl::Texture *texture =
3498                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3499             if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
3500             {
3501                 val->setError(EGL_BAD_PARAMETER, "target is not a 3D texture.");
3502                 return false;
3503             }
3504 
3505             if (texture->getBoundSurface() != nullptr)
3506             {
3507                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3508                 return false;
3509             }
3510 
3511             EGLAttrib level   = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3512             EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET, 0);
3513             if (texture->getWidth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
3514                 texture->getHeight(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
3515                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0)
3516             {
3517                 val->setError(EGL_BAD_PARAMETER,
3518                               "target 3D texture does not have a valid size at specified level.");
3519                 return false;
3520             }
3521 
3522             if (static_cast<size_t>(zOffset) >=
3523                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)))
3524             {
3525                 val->setError(EGL_BAD_PARAMETER,
3526                               "target 3D texture does not have enough layers "
3527                               "for the specified Z offset at the specified "
3528                               "level.");
3529                 return false;
3530             }
3531 
3532             bool protectedContentAttrib =
3533                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3534             if (protectedContentAttrib != texture->hasProtectedContent())
3535             {
3536                 val->setError(EGL_BAD_PARAMETER,
3537                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3538                               "of target.");
3539                 return false;
3540             }
3541 
3542             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3543         }
3544         break;
3545 
3546         case EGL_GL_RENDERBUFFER:
3547         {
3548             if (!displayExtensions.glRenderbufferImage)
3549             {
3550                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
3551                 return false;
3552             }
3553 
3554             if (attributes.contains(EGL_GL_TEXTURE_LEVEL))
3555             {
3556                 val->setError(EGL_BAD_PARAMETER,
3557                               "EGL_GL_TEXTURE_LEVEL cannot be used in "
3558                               "conjunction with a renderbuffer target.");
3559                 return false;
3560             }
3561 
3562             if (buffer == 0)
3563             {
3564                 val->setError(EGL_BAD_PARAMETER,
3565                               "buffer cannot reference a renderbuffer with the name 0.");
3566                 return false;
3567             }
3568 
3569             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3570             const gl::Renderbuffer *renderbuffer =
3571                 context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3572             if (renderbuffer == nullptr)
3573             {
3574                 val->setError(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
3575                 return false;
3576             }
3577 
3578             if (renderbuffer->getSamples() > 0)
3579             {
3580                 val->setError(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
3581                 return false;
3582             }
3583 
3584             bool protectedContentAttrib =
3585                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3586             if (protectedContentAttrib != renderbuffer->hasProtectedContent())
3587             {
3588                 val->setError(EGL_BAD_ACCESS,
3589                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3590                               "of target.");
3591                 return false;
3592             }
3593         }
3594         break;
3595 
3596         case EGL_NATIVE_BUFFER_ANDROID:
3597         {
3598             if (!displayExtensions.imageNativeBuffer)
3599             {
3600                 val->setError(EGL_BAD_PARAMETER, "EGL_ANDROID_image_native_buffer not supported.");
3601                 return false;
3602             }
3603 
3604             if (context != nullptr)
3605             {
3606                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3607                 return false;
3608             }
3609 
3610             ANGLE_EGL_TRY_RETURN(
3611                 val->eglThread,
3612                 display->validateImageClientBuffer(context, target, buffer, attributes),
3613                 val->entryPoint, val->labeledObject, false);
3614         }
3615         break;
3616 
3617         case EGL_D3D11_TEXTURE_ANGLE:
3618             if (!displayExtensions.imageD3D11Texture)
3619             {
3620                 val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_image_d3d11_texture not supported.");
3621                 return false;
3622             }
3623 
3624             if (context != nullptr)
3625             {
3626                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3627                 return false;
3628             }
3629 
3630             ANGLE_EGL_TRY_RETURN(
3631                 val->eglThread,
3632                 display->validateImageClientBuffer(context, target, buffer, attributes),
3633                 val->entryPoint, val->labeledObject, false);
3634             break;
3635 
3636         case EGL_LINUX_DMA_BUF_EXT:
3637             if (!displayExtensions.imageDmaBufImportEXT)
3638             {
3639                 val->setError(EGL_BAD_PARAMETER, "EGL_EXT_image_dma_buf_import not supported.");
3640                 return false;
3641             }
3642 
3643             if (context != nullptr)
3644             {
3645                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3646                 return false;
3647             }
3648 
3649             if (buffer != nullptr)
3650             {
3651                 val->setError(EGL_BAD_PARAMETER, "buffer must be NULL.");
3652                 return false;
3653             }
3654 
3655             {
3656                 EGLenum kRequiredParameters[] = {EGL_WIDTH,
3657                                                  EGL_HEIGHT,
3658                                                  EGL_LINUX_DRM_FOURCC_EXT,
3659                                                  EGL_DMA_BUF_PLANE0_FD_EXT,
3660                                                  EGL_DMA_BUF_PLANE0_OFFSET_EXT,
3661                                                  EGL_DMA_BUF_PLANE0_PITCH_EXT};
3662                 for (EGLenum requiredParameter : kRequiredParameters)
3663                 {
3664                     if (!attributes.contains(requiredParameter))
3665                     {
3666                         val->setError(EGL_BAD_PARAMETER,
3667                                       "Missing required parameter 0x%X for image target "
3668                                       "EGL_LINUX_DMA_BUF_EXT.",
3669                                       requiredParameter);
3670                         return false;
3671                     }
3672                 }
3673 
3674                 bool containPlane0ModifierLo =
3675                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT);
3676                 bool containPlane0ModifierHi =
3677                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT);
3678                 bool containPlane1ModifierLo =
3679                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT);
3680                 bool containPlane1ModifierHi =
3681                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT);
3682                 bool containPlane2ModifierLo =
3683                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT);
3684                 bool containPlane2ModifierHi =
3685                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT);
3686                 bool containPlane3ModifierLo =
3687                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT);
3688                 bool containPlane3ModifierHi =
3689                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT);
3690                 if ((containPlane0ModifierLo ^ containPlane0ModifierHi) ||
3691                     (containPlane1ModifierLo ^ containPlane1ModifierHi) ||
3692                     (containPlane2ModifierLo ^ containPlane2ModifierHi) ||
3693                     (containPlane3ModifierLo ^ containPlane3ModifierHi))
3694                 {
3695                     val->setError(
3696                         EGL_BAD_PARAMETER,
3697                         "the list of attributes contains EGL_DMA_BUF_PLANE*_MODIFIER_LO_EXT "
3698                         "but not EGL_DMA_BUF_PLANE*_MODIFIER_HI_EXT or vice versa.");
3699                     return false;
3700                 }
3701             }
3702             break;
3703 
3704         case EGL_METAL_TEXTURE_ANGLE:
3705             if (!displayExtensions.mtlTextureClientBuffer)
3706             {
3707                 val->setError(EGL_BAD_PARAMETER,
3708                               "EGL_ANGLE_metal_texture_client_buffer not supported.");
3709                 return false;
3710             }
3711 
3712             if (context != nullptr)
3713             {
3714                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3715                 return false;
3716             }
3717 
3718             ANGLE_EGL_TRY_RETURN(
3719                 val->eglThread,
3720                 display->validateImageClientBuffer(context, target, buffer, attributes),
3721                 val->entryPoint, val->labeledObject, false);
3722             break;
3723         default:
3724             val->setError(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
3725             return false;
3726     }
3727 
3728     if (attributes.contains(EGL_GL_TEXTURE_ZOFFSET) && target != EGL_GL_TEXTURE_3D)
3729     {
3730         val->setError(EGL_BAD_PARAMETER,
3731                       "EGL_GL_TEXTURE_ZOFFSET must be used with a 3D texture target.");
3732         return false;
3733     }
3734 
3735     return true;
3736 }
3737 
ValidateDestroyImage(const ValidationContext * val,const Display * display,const Image * image)3738 bool ValidateDestroyImage(const ValidationContext *val, const Display *display, const Image *image)
3739 {
3740     ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
3741 
3742     return true;
3743 }
3744 
ValidateCreateImageKHR(const ValidationContext * val,const Display * display,const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)3745 bool ValidateCreateImageKHR(const ValidationContext *val,
3746                             const Display *display,
3747                             const gl::Context *context,
3748                             EGLenum target,
3749                             EGLClientBuffer buffer,
3750                             const AttributeMap &attributes)
3751 {
3752     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3753 
3754     if (!display->getExtensions().imageBase && !display->getExtensions().image)
3755     {
3756         // It is out of spec what happens when calling an extension function when the extension is
3757         // not available.
3758         // EGL_BAD_DISPLAY seems like a reasonable error.
3759         val->setError(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
3760         return false;
3761     }
3762 
3763     return ValidateCreateImage(val, display, context, target, buffer, attributes);
3764 }
3765 
ValidateDestroyImageKHR(const ValidationContext * val,const Display * display,const Image * image)3766 bool ValidateDestroyImageKHR(const ValidationContext *val,
3767                              const Display *display,
3768                              const Image *image)
3769 {
3770     ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
3771 
3772     if (!display->getExtensions().imageBase && !display->getExtensions().image)
3773     {
3774         // It is out of spec what happens when calling an extension function when the extension is
3775         // not available.
3776         // EGL_BAD_DISPLAY seems like a reasonable error.
3777         val->setError(EGL_BAD_DISPLAY);
3778         return false;
3779     }
3780 
3781     return true;
3782 }
3783 
ValidateCreateDeviceANGLE(const ValidationContext * val,EGLint device_type,const void * native_device,const EGLAttrib * attrib_list)3784 bool ValidateCreateDeviceANGLE(const ValidationContext *val,
3785                                EGLint device_type,
3786                                const void *native_device,
3787                                const EGLAttrib *attrib_list)
3788 {
3789     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3790     if (!clientExtensions.deviceCreation)
3791     {
3792         val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
3793         return false;
3794     }
3795 
3796     if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
3797     {
3798         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
3799         return false;
3800     }
3801 
3802     switch (device_type)
3803     {
3804         case EGL_D3D11_DEVICE_ANGLE:
3805             if (!clientExtensions.deviceCreationD3D11)
3806             {
3807                 val->setError(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
3808                 return false;
3809             }
3810             break;
3811         default:
3812             val->setError(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
3813             return false;
3814     }
3815 
3816     return true;
3817 }
3818 
ValidateReleaseDeviceANGLE(const ValidationContext * val,const Device * device)3819 bool ValidateReleaseDeviceANGLE(const ValidationContext *val, const Device *device)
3820 {
3821     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3822     if (!clientExtensions.deviceCreation)
3823     {
3824         val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
3825         return false;
3826     }
3827 
3828     if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
3829     {
3830         val->setError(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
3831         return false;
3832     }
3833 
3834     Display *owningDisplay = device->getOwningDisplay();
3835     if (owningDisplay != nullptr)
3836     {
3837         val->setError(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
3838         return false;
3839     }
3840 
3841     return true;
3842 }
3843 
ValidateCreateSync(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs)3844 bool ValidateCreateSync(const ValidationContext *val,
3845                         const Display *display,
3846                         EGLenum type,
3847                         const AttributeMap &attribs)
3848 {
3849     return ValidateCreateSyncBase(val, display, type, attribs, false);
3850 }
3851 
ValidateCreateSyncKHR(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs)3852 bool ValidateCreateSyncKHR(const ValidationContext *val,
3853                            const Display *display,
3854                            EGLenum type,
3855                            const AttributeMap &attribs)
3856 {
3857     return ValidateCreateSyncBase(val, display, type, attribs, true);
3858 }
3859 
ValidateDestroySync(const ValidationContext * val,const Display * display,const Sync * sync)3860 bool ValidateDestroySync(const ValidationContext *val, const Display *display, const Sync *sync)
3861 {
3862     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3863     return true;
3864 }
3865 
ValidateDestroySyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked)3866 bool ValidateDestroySyncKHR(const ValidationContext *val,
3867                             const Display *dpyPacked,
3868                             const Sync *syncPacked)
3869 {
3870     return ValidateDestroySync(val, dpyPacked, syncPacked);
3871 }
3872 
ValidateClientWaitSync(const ValidationContext * val,const Display * display,const Sync * sync,EGLint flags,EGLTime timeout)3873 bool ValidateClientWaitSync(const ValidationContext *val,
3874                             const Display *display,
3875                             const Sync *sync,
3876                             EGLint flags,
3877                             EGLTime timeout)
3878 {
3879     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3880     return true;
3881 }
3882 
ValidateClientWaitSyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked,EGLint flags,EGLTimeKHR timeout)3883 bool ValidateClientWaitSyncKHR(const ValidationContext *val,
3884                                const Display *dpyPacked,
3885                                const Sync *syncPacked,
3886                                EGLint flags,
3887                                EGLTimeKHR timeout)
3888 {
3889     return ValidateClientWaitSync(val, dpyPacked, syncPacked, flags, timeout);
3890 }
3891 
ValidateWaitSync(const ValidationContext * val,const Display * display,const Sync * sync,EGLint flags)3892 bool ValidateWaitSync(const ValidationContext *val,
3893                       const Display *display,
3894                       const Sync *sync,
3895                       EGLint flags)
3896 {
3897     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3898 
3899     const DisplayExtensions &extensions = display->getExtensions();
3900     if (!extensions.waitSync)
3901     {
3902         val->setError(EGL_BAD_ACCESS, "EGL_KHR_wait_sync extension is not available");
3903         return false;
3904     }
3905 
3906     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3907 
3908     gl::Context *context = val->eglThread->getContext();
3909     if (context == nullptr)
3910     {
3911         val->setError(EGL_BAD_MATCH, "No context is current.");
3912         return false;
3913     }
3914 
3915     if (!context->getExtensions().EGLSyncOES)
3916     {
3917         val->setError(EGL_BAD_MATCH,
3918                       "Server-side waits cannot be performed without "
3919                       "GL_OES_EGL_sync support.");
3920         return false;
3921     }
3922 
3923     if (flags != 0)
3924     {
3925         val->setError(EGL_BAD_PARAMETER, "flags must be zero");
3926         return false;
3927     }
3928 
3929     return true;
3930 }
3931 
ValidateWaitSyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked,EGLint flags)3932 bool ValidateWaitSyncKHR(const ValidationContext *val,
3933                          const Display *dpyPacked,
3934                          const Sync *syncPacked,
3935                          EGLint flags)
3936 {
3937     return ValidateWaitSync(val, dpyPacked, syncPacked, flags);
3938 }
3939 
ValidateGetSyncAttrib(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute,const EGLAttrib * value)3940 bool ValidateGetSyncAttrib(const ValidationContext *val,
3941                            const Display *display,
3942                            const Sync *sync,
3943                            EGLint attribute,
3944                            const EGLAttrib *value)
3945 {
3946     if (value == nullptr)
3947     {
3948         val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
3949         return false;
3950     }
3951     return ValidateGetSyncAttribBase(val, display, sync, attribute);
3952 }
3953 
ValidateGetSyncAttribKHR(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute,const EGLint * value)3954 bool ValidateGetSyncAttribKHR(const ValidationContext *val,
3955                               const Display *display,
3956                               const Sync *sync,
3957                               EGLint attribute,
3958                               const EGLint *value)
3959 {
3960     if (value == nullptr)
3961     {
3962         val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
3963         return false;
3964     }
3965     return ValidateGetSyncAttribBase(val, display, sync, attribute);
3966 }
3967 
ValidateCreateStreamKHR(const ValidationContext * val,const Display * display,const AttributeMap & attributes)3968 bool ValidateCreateStreamKHR(const ValidationContext *val,
3969                              const Display *display,
3970                              const AttributeMap &attributes)
3971 {
3972     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3973 
3974     const DisplayExtensions &displayExtensions = display->getExtensions();
3975     if (!displayExtensions.stream)
3976     {
3977         val->setError(EGL_BAD_ALLOC, "Stream extension not active");
3978         return false;
3979     }
3980 
3981     attributes.initializeWithoutValidation();
3982 
3983     for (const auto &attributeIter : attributes)
3984     {
3985         EGLAttrib attribute = attributeIter.first;
3986         EGLAttrib value     = attributeIter.second;
3987 
3988         ANGLE_VALIDATION_TRY(ValidateStreamAttribute(val, attribute, value, displayExtensions));
3989     }
3990 
3991     return true;
3992 }
3993 
ValidateDestroyStreamKHR(const ValidationContext * val,const Display * display,const Stream * stream)3994 bool ValidateDestroyStreamKHR(const ValidationContext *val,
3995                               const Display *display,
3996                               const Stream *stream)
3997 {
3998     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
3999     return true;
4000 }
4001 
ValidateStreamAttribKHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,EGLint value)4002 bool ValidateStreamAttribKHR(const ValidationContext *val,
4003                              const Display *display,
4004                              const Stream *stream,
4005                              EGLenum attribute,
4006                              EGLint value)
4007 {
4008     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4009 
4010     if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
4011     {
4012         val->setError(EGL_BAD_STATE_KHR, "Bad stream state");
4013         return false;
4014     }
4015 
4016     return ValidateStreamAttribute(val, attribute, value, display->getExtensions());
4017 }
4018 
ValidateQueryStreamKHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,const EGLint * value)4019 bool ValidateQueryStreamKHR(const ValidationContext *val,
4020                             const Display *display,
4021                             const Stream *stream,
4022                             EGLenum attribute,
4023                             const EGLint *value)
4024 {
4025     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4026 
4027     switch (attribute)
4028     {
4029         case EGL_STREAM_STATE_KHR:
4030         case EGL_CONSUMER_LATENCY_USEC_KHR:
4031             break;
4032         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
4033             if (!display->getExtensions().streamConsumerGLTexture)
4034             {
4035                 val->setError(EGL_BAD_ATTRIBUTE, "Consumer GLTexture extension not active");
4036                 return false;
4037             }
4038             break;
4039         default:
4040             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4041             return false;
4042     }
4043 
4044     return true;
4045 }
4046 
ValidateQueryStreamu64KHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,const EGLuint64KHR * value)4047 bool ValidateQueryStreamu64KHR(const ValidationContext *val,
4048                                const Display *display,
4049                                const Stream *stream,
4050                                EGLenum attribute,
4051                                const EGLuint64KHR *value)
4052 {
4053     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4054 
4055     switch (attribute)
4056     {
4057         case EGL_CONSUMER_FRAME_KHR:
4058         case EGL_PRODUCER_FRAME_KHR:
4059             break;
4060         default:
4061             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4062             return false;
4063     }
4064 
4065     return true;
4066 }
4067 
ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext * val,const Display * display,const Stream * stream)4068 bool ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext *val,
4069                                                 const Display *display,
4070                                                 const Stream *stream)
4071 {
4072     gl::Context *context = val->eglThread->getContext();
4073     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4074 
4075     const DisplayExtensions &displayExtensions = display->getExtensions();
4076     if (!displayExtensions.streamConsumerGLTexture)
4077     {
4078         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4079         return false;
4080     }
4081 
4082     if (!context->getExtensions().EGLStreamConsumerExternalNV)
4083     {
4084         val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
4085         return false;
4086     }
4087 
4088     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4089     {
4090         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4091         return false;
4092     }
4093 
4094     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
4095     {
4096         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4097         return false;
4098     }
4099 
4100     // Lookup the texture and ensure it is correct
4101     gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
4102     if (texture == nullptr || texture->id().value == 0)
4103     {
4104         val->setError(EGL_BAD_ACCESS, "No external texture bound");
4105         return false;
4106     }
4107 
4108     return true;
4109 }
4110 
ValidateStreamConsumerAcquireKHR(const ValidationContext * val,const Display * display,const Stream * stream)4111 bool ValidateStreamConsumerAcquireKHR(const ValidationContext *val,
4112                                       const Display *display,
4113                                       const Stream *stream)
4114 {
4115     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4116 
4117     const DisplayExtensions &displayExtensions = display->getExtensions();
4118     if (!displayExtensions.streamConsumerGLTexture)
4119     {
4120         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4121         return false;
4122     }
4123 
4124     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4125     {
4126         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4127         return false;
4128     }
4129 
4130     gl::Context *context = val->eglThread->getContext();
4131     if (!context)
4132     {
4133         val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
4134         return false;
4135     }
4136 
4137     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4138 
4139     if (!stream->isConsumerBoundToContext(context))
4140     {
4141         val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
4142         return false;
4143     }
4144 
4145     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
4146         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
4147     {
4148         val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
4149         return false;
4150     }
4151 
4152     // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
4153     // However, the timeout is effectively ignored since it has no useful functionality with the
4154     // current producers that are implemented, so we don't allow that state
4155     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
4156         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
4157     {
4158         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4159         return false;
4160     }
4161 
4162     return true;
4163 }
4164 
ValidateStreamConsumerReleaseKHR(const ValidationContext * val,const Display * display,const Stream * stream)4165 bool ValidateStreamConsumerReleaseKHR(const ValidationContext *val,
4166                                       const Display *display,
4167                                       const Stream *stream)
4168 {
4169     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4170 
4171     const DisplayExtensions &displayExtensions = display->getExtensions();
4172     if (!displayExtensions.streamConsumerGLTexture)
4173     {
4174         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4175         return false;
4176     }
4177 
4178     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4179     {
4180         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4181         return false;
4182     }
4183 
4184     gl::Context *context = val->eglThread->getContext();
4185     if (!context)
4186     {
4187         val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
4188         return false;
4189     }
4190 
4191     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4192 
4193     if (!stream->isConsumerBoundToContext(context))
4194     {
4195         val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
4196         return false;
4197     }
4198 
4199     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
4200         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
4201     {
4202         val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
4203         return false;
4204     }
4205 
4206     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
4207         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
4208     {
4209         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4210         return false;
4211     }
4212 
4213     return true;
4214 }
4215 
ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext * val,const Display * display,const Stream * stream,const AttributeMap & attribs)4216 bool ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext *val,
4217                                                       const Display *display,
4218                                                       const Stream *stream,
4219                                                       const AttributeMap &attribs)
4220 {
4221     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4222 
4223     const DisplayExtensions &displayExtensions = display->getExtensions();
4224     if (!displayExtensions.streamConsumerGLTexture)
4225     {
4226         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4227         return false;
4228     }
4229 
4230     gl::Context *context = val->eglThread->getContext();
4231     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4232 
4233     // Although technically not a requirement in spec, the context needs to be checked for support
4234     // for external textures or future logic will cause assertations. This extension is also
4235     // effectively useless without external textures.
4236     if (!context->getExtensions().EGLStreamConsumerExternalNV)
4237     {
4238         val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
4239         return false;
4240     }
4241 
4242     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4243     {
4244         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4245         return false;
4246     }
4247 
4248     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
4249     {
4250         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4251         return false;
4252     }
4253 
4254     const gl::Caps &glCaps = context->getCaps();
4255 
4256     EGLAttrib colorBufferType = EGL_RGB_BUFFER;
4257     EGLAttrib planeCount      = -1;
4258     EGLAttrib plane[3];
4259     for (int i = 0; i < 3; i++)
4260     {
4261         plane[i] = -1;
4262     }
4263 
4264     attribs.initializeWithoutValidation();
4265 
4266     for (const auto &attributeIter : attribs)
4267     {
4268         EGLAttrib attribute = attributeIter.first;
4269         EGLAttrib value     = attributeIter.second;
4270 
4271         switch (attribute)
4272         {
4273             case EGL_COLOR_BUFFER_TYPE:
4274                 if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
4275                 {
4276                     val->setError(EGL_BAD_PARAMETER, "Invalid color buffer type");
4277                     return false;
4278                 }
4279                 colorBufferType = value;
4280                 break;
4281             case EGL_YUV_NUMBER_OF_PLANES_EXT:
4282                 // planeCount = -1 is a tag for the default plane count so the value must be checked
4283                 // to be positive here to ensure future logic doesn't break on invalid negative
4284                 // inputs
4285                 if (value < 0)
4286                 {
4287                     val->setError(EGL_BAD_MATCH, "Invalid plane count");
4288                     return false;
4289                 }
4290                 planeCount = value;
4291                 break;
4292             default:
4293                 if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
4294                     attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
4295                 {
4296                     if ((value < 0 ||
4297                          value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
4298                         value != EGL_NONE)
4299                     {
4300                         val->setError(EGL_BAD_ACCESS, "Invalid texture unit");
4301                         return false;
4302                     }
4303                     plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
4304                 }
4305                 else
4306                 {
4307                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4308                     return false;
4309                 }
4310         }
4311     }
4312 
4313     if (colorBufferType == EGL_RGB_BUFFER)
4314     {
4315         if (planeCount > 0)
4316         {
4317             val->setError(EGL_BAD_MATCH, "Plane count must be 0 for RGB buffer");
4318             return false;
4319         }
4320         for (int i = 0; i < 3; i++)
4321         {
4322             if (plane[i] != -1)
4323             {
4324                 val->setError(EGL_BAD_MATCH, "Planes cannot be specified");
4325                 return false;
4326             }
4327         }
4328 
4329         // Lookup the texture and ensure it is correct
4330         gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
4331         if (texture == nullptr || texture->id().value == 0)
4332         {
4333             val->setError(EGL_BAD_ACCESS, "No external texture bound");
4334             return false;
4335         }
4336     }
4337     else
4338     {
4339         if (planeCount == -1)
4340         {
4341             planeCount = 2;
4342         }
4343         if (planeCount < 1 || planeCount > 3)
4344         {
4345             val->setError(EGL_BAD_MATCH, "Invalid YUV plane count");
4346             return false;
4347         }
4348         for (EGLAttrib i = planeCount; i < 3; i++)
4349         {
4350             if (plane[i] != -1)
4351             {
4352                 val->setError(EGL_BAD_MATCH, "Invalid plane specified");
4353                 return false;
4354             }
4355         }
4356 
4357         // Set to ensure no texture is referenced more than once
4358         std::set<gl::Texture *> textureSet;
4359         for (EGLAttrib i = 0; i < planeCount; i++)
4360         {
4361             if (plane[i] == -1)
4362             {
4363                 val->setError(EGL_BAD_MATCH, "Not all planes specified");
4364                 return false;
4365             }
4366             if (plane[i] != EGL_NONE)
4367             {
4368                 gl::Texture *texture = context->getState().getSamplerTexture(
4369                     static_cast<unsigned int>(plane[i]), gl::TextureType::External);
4370                 if (texture == nullptr || texture->id().value == 0)
4371                 {
4372                     val->setError(
4373                         EGL_BAD_ACCESS,
4374                         "No external texture bound at one or more specified texture units");
4375                     return false;
4376                 }
4377                 if (textureSet.find(texture) != textureSet.end())
4378                 {
4379                     val->setError(EGL_BAD_ACCESS, "Multiple planes bound to same texture object");
4380                     return false;
4381                 }
4382                 textureSet.insert(texture);
4383             }
4384         }
4385     }
4386 
4387     return true;
4388 }
4389 
ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext * val,const Display * display,const Stream * stream,const AttributeMap & attribs)4390 bool ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext *val,
4391                                                  const Display *display,
4392                                                  const Stream *stream,
4393                                                  const AttributeMap &attribs)
4394 {
4395     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4396 
4397     const DisplayExtensions &displayExtensions = display->getExtensions();
4398     if (!displayExtensions.streamProducerD3DTexture)
4399     {
4400         val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
4401         return false;
4402     }
4403 
4404     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4405 
4406     attribs.initializeWithoutValidation();
4407 
4408     if (!attribs.isEmpty())
4409     {
4410         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4411         return false;
4412     }
4413 
4414     if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
4415     {
4416         val->setError(EGL_BAD_STATE_KHR, "Stream not in connecting state");
4417         return false;
4418     }
4419 
4420     switch (stream->getConsumerType())
4421     {
4422         case Stream::ConsumerType::GLTextureYUV:
4423             if (stream->getPlaneCount() != 2)
4424             {
4425                 val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4426                 return false;
4427             }
4428             break;
4429 
4430         case Stream::ConsumerType::GLTextureRGB:
4431             if (stream->getPlaneCount() != 1)
4432             {
4433                 val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4434                 return false;
4435             }
4436             break;
4437 
4438         default:
4439             val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4440             return false;
4441     }
4442 
4443     return true;
4444 }
4445 
ValidateStreamPostD3DTextureANGLE(const ValidationContext * val,const Display * display,const Stream * stream,const void * texture,const AttributeMap & attribs)4446 bool ValidateStreamPostD3DTextureANGLE(const ValidationContext *val,
4447                                        const Display *display,
4448                                        const Stream *stream,
4449                                        const void *texture,
4450                                        const AttributeMap &attribs)
4451 {
4452     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4453 
4454     const DisplayExtensions &displayExtensions = display->getExtensions();
4455     if (!displayExtensions.streamProducerD3DTexture)
4456     {
4457         val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
4458         return false;
4459     }
4460 
4461     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4462 
4463     attribs.initializeWithoutValidation();
4464 
4465     for (auto &attributeIter : attribs)
4466     {
4467         EGLAttrib attribute = attributeIter.first;
4468         EGLAttrib value     = attributeIter.second;
4469 
4470         switch (attribute)
4471         {
4472             case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
4473                 if (value < 0)
4474                 {
4475                     val->setError(EGL_BAD_PARAMETER, "Invalid subresource index");
4476                     return false;
4477                 }
4478                 break;
4479             case EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG:
4480                 if (value < 0)
4481                 {
4482                     val->setError(EGL_BAD_PARAMETER, "Invalid plane offset");
4483                     return false;
4484                 }
4485                 break;
4486             default:
4487                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4488                 return false;
4489         }
4490     }
4491 
4492     if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
4493         stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
4494         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
4495     {
4496         val->setError(EGL_BAD_STATE_KHR, "Stream not fully configured");
4497         return false;
4498     }
4499 
4500     if (stream->getProducerType() != Stream::ProducerType::D3D11Texture)
4501     {
4502         val->setError(EGL_BAD_MATCH, "Incompatible stream producer");
4503         return false;
4504     }
4505 
4506     if (texture == nullptr)
4507     {
4508         val->setError(EGL_BAD_PARAMETER, "Texture is null");
4509         return false;
4510     }
4511 
4512     ANGLE_EGL_TRY_RETURN(val->eglThread, stream->validateD3D11Texture(texture, attribs),
4513                          val->entryPoint, val->labeledObject, false);
4514 
4515     return true;
4516 }
4517 
ValidateSyncControlCHROMIUM(const ValidationContext * val,const Display * display,const Surface * eglSurface)4518 bool ValidateSyncControlCHROMIUM(const ValidationContext *val,
4519                                  const Display *display,
4520                                  const Surface *eglSurface)
4521 {
4522     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4523     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4524 
4525     const DisplayExtensions &displayExtensions = display->getExtensions();
4526     if (!displayExtensions.syncControlCHROMIUM)
4527     {
4528         val->setError(EGL_BAD_ACCESS, "syncControlCHROMIUM extension not active");
4529         return false;
4530     }
4531 
4532     return true;
4533 }
4534 
ValidateSyncControlRateANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface)4535 bool ValidateSyncControlRateANGLE(const ValidationContext *val,
4536                                   const Display *display,
4537                                   const Surface *eglSurface)
4538 {
4539     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4540     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4541 
4542     const DisplayExtensions &displayExtensions = display->getExtensions();
4543     if (!displayExtensions.syncControlRateANGLE)
4544     {
4545         val->setError(EGL_BAD_ACCESS, "syncControlRateANGLE extension not active");
4546         return false;
4547     }
4548 
4549     return true;
4550 }
4551 
ValidateGetMscRateANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface,const EGLint * numerator,const EGLint * denominator)4552 bool ValidateGetMscRateANGLE(const ValidationContext *val,
4553                              const Display *display,
4554                              const Surface *eglSurface,
4555                              const EGLint *numerator,
4556                              const EGLint *denominator)
4557 {
4558     ANGLE_VALIDATION_TRY(ValidateSyncControlRateANGLE(val, display, eglSurface));
4559 
4560     if (numerator == nullptr)
4561     {
4562         val->setError(EGL_BAD_PARAMETER, "numerator is null");
4563         return false;
4564     }
4565     if (denominator == nullptr)
4566     {
4567         val->setError(EGL_BAD_PARAMETER, "denominator is null");
4568         return false;
4569     }
4570 
4571     return true;
4572 }
4573 
ValidateGetSyncValuesCHROMIUM(const ValidationContext * val,const Display * display,const Surface * eglSurface,const EGLuint64KHR * ust,const EGLuint64KHR * msc,const EGLuint64KHR * sbc)4574 bool ValidateGetSyncValuesCHROMIUM(const ValidationContext *val,
4575                                    const Display *display,
4576                                    const Surface *eglSurface,
4577                                    const EGLuint64KHR *ust,
4578                                    const EGLuint64KHR *msc,
4579                                    const EGLuint64KHR *sbc)
4580 {
4581     ANGLE_VALIDATION_TRY(ValidateSyncControlCHROMIUM(val, display, eglSurface));
4582 
4583     if (ust == nullptr)
4584     {
4585         val->setError(EGL_BAD_PARAMETER, "ust is null");
4586         return false;
4587     }
4588     if (msc == nullptr)
4589     {
4590         val->setError(EGL_BAD_PARAMETER, "msc is null");
4591         return false;
4592     }
4593     if (sbc == nullptr)
4594     {
4595         val->setError(EGL_BAD_PARAMETER, "sbc is null");
4596         return false;
4597     }
4598 
4599     return true;
4600 }
4601 
ValidateDestroySurface(const ValidationContext * val,const Display * display,const Surface * surface)4602 bool ValidateDestroySurface(const ValidationContext *val,
4603                             const Display *display,
4604                             const Surface *surface)
4605 {
4606     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4607     return true;
4608 }
4609 
ValidateDestroyContext(const ValidationContext * val,const Display * display,const gl::Context * glCtx)4610 bool ValidateDestroyContext(const ValidationContext *val,
4611                             const Display *display,
4612                             const gl::Context *glCtx)
4613 {
4614     ANGLE_VALIDATION_TRY(ValidateContext(val, display, glCtx));
4615     return true;
4616 }
4617 
ValidateSwapBuffers(const ValidationContext * val,const Display * display,const Surface * eglSurface)4618 bool ValidateSwapBuffers(const ValidationContext *val,
4619                          const Display *display,
4620                          const Surface *eglSurface)
4621 {
4622     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4623 
4624     if (display->isDeviceLost())
4625     {
4626         val->setError(EGL_CONTEXT_LOST);
4627         return false;
4628     }
4629 
4630     if (eglSurface->isLocked())
4631     {
4632         val->setError(EGL_BAD_ACCESS);
4633         return false;
4634     }
4635 
4636     if (eglSurface == EGL_NO_SURFACE || !val->eglThread->getContext() ||
4637         val->eglThread->getCurrentDrawSurface() != eglSurface)
4638     {
4639         val->setError(EGL_BAD_SURFACE);
4640         return false;
4641     }
4642 
4643     return true;
4644 }
4645 
ValidateSwapBuffersWithDamageKHR(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint * rects,EGLint n_rects)4646 bool ValidateSwapBuffersWithDamageKHR(const ValidationContext *val,
4647                                       const Display *display,
4648                                       const Surface *surface,
4649                                       const EGLint *rects,
4650                                       EGLint n_rects)
4651 {
4652     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4653 
4654     if (!display->getExtensions().swapBuffersWithDamage)
4655     {
4656         // It is out of spec what happens when calling an extension function when the extension is
4657         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
4658         val->setError(EGL_BAD_DISPLAY, "EGL_KHR_swap_buffers_with_damage is not available.");
4659         return false;
4660     }
4661 
4662     if (surface == EGL_NO_SURFACE)
4663     {
4664         val->setError(EGL_BAD_SURFACE, "Swap surface cannot be EGL_NO_SURFACE.");
4665         return false;
4666     }
4667 
4668     if (n_rects < 0)
4669     {
4670         val->setError(EGL_BAD_PARAMETER, "n_rects cannot be negative.");
4671         return false;
4672     }
4673 
4674     if (n_rects > 0 && rects == nullptr)
4675     {
4676         val->setError(EGL_BAD_PARAMETER, "n_rects cannot be greater than zero when rects is NULL.");
4677         return false;
4678     }
4679 
4680     if (surface->isLocked())
4681     {
4682         val->setError(EGL_BAD_ACCESS);
4683         return false;
4684     }
4685 
4686     // TODO(jmadill): Validate Surface is bound to the thread.
4687 
4688     return true;
4689 }
4690 
ValidateWaitNative(const ValidationContext * val,const EGLint engine)4691 bool ValidateWaitNative(const ValidationContext *val, const EGLint engine)
4692 {
4693     if (val->eglThread->getDisplay() == nullptr)
4694     {
4695         // EGL spec says this about eglWaitNative -
4696         //    eglWaitNative is ignored if there is no current EGL rendering context.
4697         return true;
4698     }
4699 
4700     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
4701 
4702     if (engine != EGL_CORE_NATIVE_ENGINE)
4703     {
4704         val->setError(EGL_BAD_PARAMETER, "the 'engine' parameter has an unrecognized value");
4705         return false;
4706     }
4707 
4708     return true;
4709 }
4710 
ValidateCopyBuffers(const ValidationContext * val,const Display * display,const Surface * surface,EGLNativePixmapType target)4711 bool ValidateCopyBuffers(const ValidationContext *val,
4712                          const Display *display,
4713                          const Surface *surface,
4714                          EGLNativePixmapType target)
4715 {
4716     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4717 
4718     if (display->isDeviceLost())
4719     {
4720         val->setError(EGL_CONTEXT_LOST);
4721         return false;
4722     }
4723 
4724     return true;
4725 }
4726 
ValidateBindTexImage(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint buffer)4727 bool ValidateBindTexImage(const ValidationContext *val,
4728                           const Display *display,
4729                           const Surface *surface,
4730                           const EGLint buffer)
4731 {
4732     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4733 
4734     if (buffer != EGL_BACK_BUFFER)
4735     {
4736         val->setError(EGL_BAD_PARAMETER);
4737         return false;
4738     }
4739 
4740     if (surface->getType() == EGL_WINDOW_BIT)
4741     {
4742         val->setError(EGL_BAD_SURFACE);
4743         return false;
4744     }
4745 
4746     if (surface->getBoundTexture())
4747     {
4748         val->setError(EGL_BAD_ACCESS);
4749         return false;
4750     }
4751 
4752     if (surface->getTextureFormat() == TextureFormat::NoTexture)
4753     {
4754         val->setError(EGL_BAD_MATCH);
4755         return false;
4756     }
4757 
4758     if (surface->isLocked())
4759     {
4760         val->setError(EGL_BAD_ACCESS);
4761         return false;
4762     }
4763 
4764     gl::Context *context = val->eglThread->getContext();
4765     if (context)
4766     {
4767         gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
4768         gl::Texture *textureObject = context->getTextureByType(type);
4769         ASSERT(textureObject != nullptr);
4770 
4771         if (textureObject->getImmutableFormat())
4772         {
4773             val->setError(EGL_BAD_MATCH);
4774             return false;
4775         }
4776     }
4777 
4778     return true;
4779 }
4780 
ValidateReleaseTexImage(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint buffer)4781 bool ValidateReleaseTexImage(const ValidationContext *val,
4782                              const Display *display,
4783                              const Surface *surface,
4784                              const EGLint buffer)
4785 {
4786     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4787 
4788     if (buffer != EGL_BACK_BUFFER)
4789     {
4790         val->setError(EGL_BAD_PARAMETER);
4791         return false;
4792     }
4793 
4794     if (surface->getType() == EGL_WINDOW_BIT)
4795     {
4796         val->setError(EGL_BAD_SURFACE);
4797         return false;
4798     }
4799 
4800     if (surface->getTextureFormat() == TextureFormat::NoTexture)
4801     {
4802         val->setError(EGL_BAD_MATCH);
4803         return false;
4804     }
4805 
4806     return true;
4807 }
4808 
ValidateSwapInterval(const ValidationContext * val,const Display * display,EGLint interval)4809 bool ValidateSwapInterval(const ValidationContext *val, const Display *display, EGLint interval)
4810 {
4811     const gl::Context *context = val->eglThread->getContext();
4812     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4813 
4814     Surface *drawSurface = val->eglThread->getCurrentDrawSurface();
4815     if (drawSurface == nullptr)
4816     {
4817         val->setError(EGL_BAD_SURFACE);
4818         return false;
4819     }
4820 
4821     return true;
4822 }
4823 
ValidateBindAPI(const ValidationContext * val,const EGLenum api)4824 bool ValidateBindAPI(const ValidationContext *val, const EGLenum api)
4825 {
4826     switch (api)
4827     {
4828         case EGL_OPENGL_API:
4829         case EGL_OPENVG_API:
4830             val->setError(EGL_BAD_PARAMETER);
4831             return false;  // Not supported by this implementation
4832         case EGL_OPENGL_ES_API:
4833             break;
4834         default:
4835             val->setError(EGL_BAD_PARAMETER);
4836             return false;
4837     }
4838 
4839     return true;
4840 }
4841 
ValidatePresentationTimeANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLnsecsANDROID time)4842 bool ValidatePresentationTimeANDROID(const ValidationContext *val,
4843                                      const Display *display,
4844                                      const Surface *surface,
4845                                      EGLnsecsANDROID time)
4846 {
4847     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4848 
4849     if (!display->getExtensions().presentationTime)
4850     {
4851         // It is out of spec what happens when calling an extension function when the extension is
4852         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
4853         val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_presentation_time is not available.");
4854         return false;
4855     }
4856 
4857     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4858 
4859     return true;
4860 }
4861 
ValidateSetBlobCacheFuncsANDROID(const ValidationContext * val,const Display * display,EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)4862 bool ValidateSetBlobCacheFuncsANDROID(const ValidationContext *val,
4863                                       const Display *display,
4864                                       EGLSetBlobFuncANDROID set,
4865                                       EGLGetBlobFuncANDROID get)
4866 {
4867     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4868 
4869     if (display->areBlobCacheFuncsSet())
4870     {
4871         val->setError(EGL_BAD_PARAMETER,
4872                       "Blob cache functions can only be set once in the lifetime of a Display");
4873         return false;
4874     }
4875 
4876     if (set == nullptr || get == nullptr)
4877     {
4878         val->setError(EGL_BAD_PARAMETER, "Blob cache callbacks cannot be null.");
4879         return false;
4880     }
4881 
4882     return true;
4883 }
4884 
ValidateGetConfigAttrib(const ValidationContext * val,const Display * display,const Config * config,EGLint attribute,const EGLint * value)4885 bool ValidateGetConfigAttrib(const ValidationContext *val,
4886                              const Display *display,
4887                              const Config *config,
4888                              EGLint attribute,
4889                              const EGLint *value)
4890 {
4891     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
4892     ANGLE_TRY(ValidateConfigAttribute(val, display, static_cast<EGLAttrib>(attribute)));
4893     return true;
4894 }
4895 
ValidateChooseConfig(const ValidationContext * val,const Display * display,const AttributeMap & attribs,const EGLConfig * configs,EGLint configSize,const EGLint * numConfig)4896 bool ValidateChooseConfig(const ValidationContext *val,
4897                           const Display *display,
4898                           const AttributeMap &attribs,
4899                           const EGLConfig *configs,
4900                           EGLint configSize,
4901                           const EGLint *numConfig)
4902 {
4903     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4904     ANGLE_VALIDATION_TRY(ValidateConfigAttributes(val, display, attribs));
4905 
4906     if (numConfig == nullptr)
4907     {
4908         val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
4909         return false;
4910     }
4911 
4912     return true;
4913 }
4914 
ValidateGetConfigs(const ValidationContext * val,const Display * display,const EGLConfig * configs,EGLint configSize,const EGLint * numConfig)4915 bool ValidateGetConfigs(const ValidationContext *val,
4916                         const Display *display,
4917                         const EGLConfig *configs,
4918                         EGLint configSize,
4919                         const EGLint *numConfig)
4920 {
4921     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4922 
4923     if (numConfig == nullptr)
4924     {
4925         val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
4926         return false;
4927     }
4928 
4929     return true;
4930 }
4931 
ValidateGetPlatformDisplay(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)4932 bool ValidateGetPlatformDisplay(const ValidationContext *val,
4933                                 EGLenum platform,
4934                                 const void *native_display,
4935                                 const AttributeMap &attribMap)
4936 {
4937     return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
4938 }
4939 
ValidateGetPlatformDisplayEXT(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)4940 bool ValidateGetPlatformDisplayEXT(const ValidationContext *val,
4941                                    EGLenum platform,
4942                                    const void *native_display,
4943                                    const AttributeMap &attribMap)
4944 {
4945     return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
4946 }
4947 
ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext * val,const Display * display,const Config * configuration,const void * nativeWindow,const AttributeMap & attributes)4948 bool ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext *val,
4949                                             const Display *display,
4950                                             const Config *configuration,
4951                                             const void *nativeWindow,
4952                                             const AttributeMap &attributes)
4953 {
4954     if (!Display::GetClientExtensions().platformBase)
4955     {
4956         val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
4957         return false;
4958     }
4959 
4960     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
4961 
4962     val->setError(EGL_BAD_DISPLAY, "ValidateCreatePlatformWindowSurfaceEXT unimplemented.");
4963     return false;
4964 }
4965 
ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext * val,const Display * display,const Config * configuration,const void * nativePixmap,const AttributeMap & attributes)4966 bool ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext *val,
4967                                             const Display *display,
4968                                             const Config *configuration,
4969                                             const void *nativePixmap,
4970                                             const AttributeMap &attributes)
4971 {
4972     if (!Display::GetClientExtensions().platformBase)
4973     {
4974         val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
4975         return false;
4976     }
4977 
4978     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
4979 
4980     val->setError(EGL_BAD_DISPLAY, "ValidateCreatePlatformPixmapSurfaceEXT unimplemented.");
4981     return false;
4982 }
4983 
ValidateProgramCacheGetAttribANGLE(const ValidationContext * val,const Display * display,EGLenum attrib)4984 bool ValidateProgramCacheGetAttribANGLE(const ValidationContext *val,
4985                                         const Display *display,
4986                                         EGLenum attrib)
4987 {
4988     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4989 
4990     if (!display->getExtensions().programCacheControlANGLE)
4991     {
4992         val->setError(EGL_BAD_ACCESS, "Extension not supported");
4993         return false;
4994     }
4995 
4996     switch (attrib)
4997     {
4998         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
4999         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
5000             break;
5001 
5002         default:
5003             val->setError(EGL_BAD_PARAMETER, "Invalid program cache attribute.");
5004             return false;
5005     }
5006 
5007     return true;
5008 }
5009 
ValidateProgramCacheQueryANGLE(const ValidationContext * val,const Display * display,EGLint index,const void * key,const EGLint * keysize,const void * binary,const EGLint * binarysize)5010 bool ValidateProgramCacheQueryANGLE(const ValidationContext *val,
5011                                     const Display *display,
5012                                     EGLint index,
5013                                     const void *key,
5014                                     const EGLint *keysize,
5015                                     const void *binary,
5016                                     const EGLint *binarysize)
5017 {
5018     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5019 
5020     if (!display->getExtensions().programCacheControlANGLE)
5021     {
5022         val->setError(EGL_BAD_ACCESS, "Extension not supported");
5023         return false;
5024     }
5025 
5026     if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
5027     {
5028         val->setError(EGL_BAD_PARAMETER, "Program index out of range.");
5029         return false;
5030     }
5031 
5032     if (keysize == nullptr || binarysize == nullptr)
5033     {
5034         val->setError(EGL_BAD_PARAMETER, "keysize and binarysize must always be valid pointers.");
5035         return false;
5036     }
5037 
5038     if (binary && *keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
5039     {
5040         val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
5041         return false;
5042     }
5043 
5044     if ((key == nullptr) != (binary == nullptr))
5045     {
5046         val->setError(EGL_BAD_PARAMETER, "key and binary must both be null or both non-null.");
5047         return false;
5048     }
5049 
5050     return true;
5051 }
5052 
ValidateProgramCachePopulateANGLE(const ValidationContext * val,const Display * display,const void * key,EGLint keysize,const void * binary,EGLint binarysize)5053 bool ValidateProgramCachePopulateANGLE(const ValidationContext *val,
5054                                        const Display *display,
5055                                        const void *key,
5056                                        EGLint keysize,
5057                                        const void *binary,
5058                                        EGLint binarysize)
5059 {
5060     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5061 
5062     if (!display->getExtensions().programCacheControlANGLE)
5063     {
5064         val->setError(EGL_BAD_ACCESS, "Extension not supported");
5065         return false;
5066     }
5067 
5068     if (keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
5069     {
5070         val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
5071         return false;
5072     }
5073 
5074     if (key == nullptr || binary == nullptr)
5075     {
5076         val->setError(EGL_BAD_PARAMETER, "null pointer in arguments.");
5077         return false;
5078     }
5079 
5080     // Upper bound for binarysize is arbitrary.
5081     if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
5082     {
5083         val->setError(EGL_BAD_PARAMETER, "binarysize out of valid range.");
5084         return false;
5085     }
5086 
5087     return true;
5088 }
5089 
ValidateProgramCacheResizeANGLE(const ValidationContext * val,const Display * display,EGLint limit,EGLint mode)5090 bool ValidateProgramCacheResizeANGLE(const ValidationContext *val,
5091                                      const Display *display,
5092                                      EGLint limit,
5093                                      EGLint mode)
5094 {
5095     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5096 
5097     if (!display->getExtensions().programCacheControlANGLE)
5098     {
5099         val->setError(EGL_BAD_ACCESS, "Extension not supported");
5100         return false;
5101     }
5102 
5103     if (limit < 0)
5104     {
5105         val->setError(EGL_BAD_PARAMETER, "limit must be non-negative.");
5106         return false;
5107     }
5108 
5109     switch (mode)
5110     {
5111         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
5112         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
5113             break;
5114 
5115         default:
5116             val->setError(EGL_BAD_PARAMETER, "Invalid cache resize mode.");
5117             return false;
5118     }
5119 
5120     return true;
5121 }
5122 
ValidateSurfaceAttrib(const ValidationContext * val,const Display * display,const Surface * surface,EGLint attribute,EGLint value)5123 bool ValidateSurfaceAttrib(const ValidationContext *val,
5124                            const Display *display,
5125                            const Surface *surface,
5126                            EGLint attribute,
5127                            EGLint value)
5128 {
5129     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5130     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5131 
5132     if (surface == EGL_NO_SURFACE)
5133     {
5134         val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
5135         return false;
5136     }
5137 
5138     switch (attribute)
5139     {
5140         case EGL_MIPMAP_LEVEL:
5141             break;
5142 
5143         case EGL_MULTISAMPLE_RESOLVE:
5144             switch (value)
5145             {
5146                 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
5147                     break;
5148 
5149                 case EGL_MULTISAMPLE_RESOLVE_BOX:
5150                     if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
5151                     {
5152                         val->setError(EGL_BAD_MATCH,
5153                                       "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.");
5154                         return false;
5155                     }
5156                     break;
5157 
5158                 default:
5159                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid multisample resolve type.");
5160                     return false;
5161             }
5162             break;
5163 
5164         case EGL_SWAP_BEHAVIOR:
5165             switch (value)
5166             {
5167                 case EGL_BUFFER_PRESERVED:
5168                     if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
5169                     {
5170                         val->setError(EGL_BAD_MATCH,
5171                                       "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.");
5172                         return false;
5173                     }
5174                     break;
5175 
5176                 case EGL_BUFFER_DESTROYED:
5177                     break;
5178 
5179                 default:
5180                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid swap behaviour.");
5181                     return false;
5182             }
5183             break;
5184 
5185         case EGL_WIDTH:
5186         case EGL_HEIGHT:
5187             if (!display->getExtensions().windowFixedSize)
5188             {
5189                 val->setError(EGL_BAD_ATTRIBUTE,
5190                               "EGL_WIDTH or EGL_HEIGHT cannot be set without "
5191                               "EGL_ANGLE_window_fixed_size support.");
5192                 return false;
5193             }
5194             if (!surface->isFixedSize())
5195             {
5196                 val->setError(EGL_BAD_MATCH,
5197                               "EGL_WIDTH or EGL_HEIGHT cannot be set without "
5198                               "EGL_FIXED_SIZE_ANGLE being enabled on the surface.");
5199                 return false;
5200             }
5201             break;
5202 
5203         case EGL_TIMESTAMPS_ANDROID:
5204             if (!display->getExtensions().getFrameTimestamps)
5205             {
5206                 val->setError(EGL_BAD_ATTRIBUTE,
5207                               "EGL_TIMESTAMPS_ANDROID cannot be used without "
5208                               "EGL_ANDROID_get_frame_timestamps support.");
5209                 return false;
5210             }
5211             switch (value)
5212             {
5213                 case EGL_TRUE:
5214                 case EGL_FALSE:
5215                     break;
5216 
5217                 default:
5218                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid value.");
5219                     return false;
5220             }
5221             break;
5222 
5223         case EGL_RENDER_BUFFER:
5224             if (!display->getExtensions().mutableRenderBufferKHR)
5225             {
5226                 val->setError(
5227                     EGL_BAD_ATTRIBUTE,
5228                     "Attribute EGL_RENDER_BUFFER requires EGL_KHR_mutable_render_buffer.");
5229                 return false;
5230             }
5231 
5232             if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER)
5233             {
5234                 val->setError(EGL_BAD_ATTRIBUTE,
5235                               "EGL_RENDER_BUFFER must be EGL_BACK_BUFFER or EGL_SINGLE_BUFFER.");
5236                 return false;
5237             }
5238 
5239             if ((surface->getConfig()->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) == 0)
5240             {
5241                 val->setError(EGL_BAD_MATCH,
5242                               "EGL_RENDER_BUFFER requires the surface type bit "
5243                               "EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.");
5244                 return false;
5245             }
5246             break;
5247 
5248         default:
5249             val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
5250             return false;
5251     }
5252 
5253     return true;
5254 }
5255 
ValidateQuerySurface(const ValidationContext * val,const Display * display,const Surface * surface,EGLint attribute,const EGLint * value)5256 bool ValidateQuerySurface(const ValidationContext *val,
5257                           const Display *display,
5258                           const Surface *surface,
5259                           EGLint attribute,
5260                           const EGLint *value)
5261 {
5262     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5263     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5264 
5265     if (surface == EGL_NO_SURFACE)
5266     {
5267         val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
5268         return false;
5269     }
5270 
5271     switch (attribute)
5272     {
5273         case EGL_GL_COLORSPACE:
5274         case EGL_VG_ALPHA_FORMAT:
5275         case EGL_VG_COLORSPACE:
5276         case EGL_CONFIG_ID:
5277         case EGL_HEIGHT:
5278         case EGL_HORIZONTAL_RESOLUTION:
5279         case EGL_LARGEST_PBUFFER:
5280         case EGL_MIPMAP_TEXTURE:
5281         case EGL_MIPMAP_LEVEL:
5282         case EGL_MULTISAMPLE_RESOLVE:
5283         case EGL_PIXEL_ASPECT_RATIO:
5284         case EGL_RENDER_BUFFER:
5285         case EGL_SWAP_BEHAVIOR:
5286         case EGL_TEXTURE_FORMAT:
5287         case EGL_TEXTURE_TARGET:
5288         case EGL_VERTICAL_RESOLUTION:
5289         case EGL_WIDTH:
5290             break;
5291 
5292         case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
5293             if (!display->getExtensions().postSubBuffer)
5294             {
5295                 val->setError(EGL_BAD_ATTRIBUTE,
5296                               "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
5297                               "without EGL_ANGLE_surface_orientation support.");
5298                 return false;
5299             }
5300             break;
5301 
5302         case EGL_FIXED_SIZE_ANGLE:
5303             if (!display->getExtensions().windowFixedSize)
5304             {
5305                 val->setError(EGL_BAD_ATTRIBUTE,
5306                               "EGL_FIXED_SIZE_ANGLE cannot be used without "
5307                               "EGL_ANGLE_window_fixed_size support.");
5308                 return false;
5309             }
5310             break;
5311 
5312         case EGL_SURFACE_ORIENTATION_ANGLE:
5313             if (!display->getExtensions().surfaceOrientation)
5314             {
5315                 val->setError(EGL_BAD_ATTRIBUTE,
5316                               "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
5317                               "queried without "
5318                               "EGL_ANGLE_surface_orientation support.");
5319                 return false;
5320             }
5321             break;
5322 
5323         case EGL_DIRECT_COMPOSITION_ANGLE:
5324             if (!display->getExtensions().directComposition)
5325             {
5326                 val->setError(EGL_BAD_ATTRIBUTE,
5327                               "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
5328                               "used without "
5329                               "EGL_ANGLE_direct_composition support.");
5330                 return false;
5331             }
5332             break;
5333 
5334         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
5335             if (!display->getExtensions().robustResourceInitializationANGLE)
5336             {
5337                 val->setError(EGL_BAD_ATTRIBUTE,
5338                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
5339                               "used without EGL_ANGLE_robust_resource_initialization "
5340                               "support.");
5341                 return false;
5342             }
5343             break;
5344 
5345         case EGL_TIMESTAMPS_ANDROID:
5346             if (!display->getExtensions().getFrameTimestamps)
5347             {
5348                 val->setError(EGL_BAD_ATTRIBUTE,
5349                               "EGL_TIMESTAMPS_ANDROID cannot be used without "
5350                               "EGL_ANDROID_get_frame_timestamps support.");
5351                 return false;
5352             }
5353             break;
5354 
5355         case EGL_BUFFER_AGE_EXT:
5356         {
5357             if (!display->getExtensions().bufferAgeEXT)
5358             {
5359                 val->setError(EGL_BAD_ATTRIBUTE,
5360                               "EGL_BUFFER_AGE_EXT cannot be used without "
5361                               "EGL_EXT_buffer_age support.");
5362                 return false;
5363             }
5364             gl::Context *context = val->eglThread->getContext();
5365             if ((context == nullptr) || (context->getCurrentDrawSurface() != surface))
5366             {
5367                 val->setError(EGL_BAD_SURFACE,
5368                               "The surface must be current to the current context "
5369                               "in order to query buffer age per extension "
5370                               "EGL_EXT_buffer_age.");
5371                 return false;
5372             }
5373         }
5374         break;
5375 
5376         case EGL_BITMAP_PITCH_KHR:
5377         case EGL_BITMAP_ORIGIN_KHR:
5378         case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
5379         case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
5380         case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
5381         case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
5382         case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
5383         case EGL_BITMAP_PIXEL_SIZE_KHR:
5384             if (!display->getExtensions().lockSurface3KHR)
5385             {
5386                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not supported.");
5387                 return false;
5388             }
5389             break;
5390 
5391         default:
5392             val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
5393             return false;
5394     }
5395 
5396     return true;
5397 }
5398 
ValidateQueryContext(const ValidationContext * val,const Display * display,const gl::Context * context,EGLint attribute,const EGLint * value)5399 bool ValidateQueryContext(const ValidationContext *val,
5400                           const Display *display,
5401                           const gl::Context *context,
5402                           EGLint attribute,
5403                           const EGLint *value)
5404 {
5405     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
5406 
5407     switch (attribute)
5408     {
5409         case EGL_CONFIG_ID:
5410         case EGL_CONTEXT_CLIENT_TYPE:
5411         case EGL_CONTEXT_CLIENT_VERSION:
5412         case EGL_RENDER_BUFFER:
5413             break;
5414 
5415         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
5416             if (!display->getExtensions().robustResourceInitializationANGLE)
5417             {
5418                 val->setError(EGL_BAD_ATTRIBUTE,
5419                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
5420                               "used without EGL_ANGLE_robust_resource_initialization "
5421                               "support.");
5422                 return false;
5423             }
5424             break;
5425 
5426         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
5427             if (!display->getExtensions().contextPriority)
5428             {
5429                 val->setError(EGL_BAD_ATTRIBUTE,
5430                               "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
5431                               "extension EGL_IMG_context_priority.");
5432                 return false;
5433             }
5434             break;
5435 
5436         default:
5437             val->setError(EGL_BAD_ATTRIBUTE, "Invalid context attribute: 0x%04X", attribute);
5438             return false;
5439     }
5440 
5441     return true;
5442 }
5443 
ValidateDebugMessageControlKHR(const ValidationContext * val,EGLDEBUGPROCKHR callback,const AttributeMap & attribs)5444 bool ValidateDebugMessageControlKHR(const ValidationContext *val,
5445                                     EGLDEBUGPROCKHR callback,
5446                                     const AttributeMap &attribs)
5447 {
5448     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5449     if (!clientExtensions.debug)
5450     {
5451         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5452         return false;
5453     }
5454 
5455     attribs.initializeWithoutValidation();
5456 
5457     for (const auto &attrib : attribs)
5458     {
5459         switch (attrib.first)
5460         {
5461             case EGL_DEBUG_MSG_CRITICAL_KHR:
5462             case EGL_DEBUG_MSG_ERROR_KHR:
5463             case EGL_DEBUG_MSG_WARN_KHR:
5464             case EGL_DEBUG_MSG_INFO_KHR:
5465                 if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
5466                 {
5467                     val->setError(EGL_BAD_ATTRIBUTE,
5468                                   "message controls must be EGL_TRUE or EGL_FALSE.");
5469                     return false;
5470                 }
5471                 break;
5472         }
5473     }
5474 
5475     return true;
5476 }
5477 
ValidateQueryDebugKHR(const ValidationContext * val,EGLint attribute,const EGLAttrib * value)5478 bool ValidateQueryDebugKHR(const ValidationContext *val, EGLint attribute, const EGLAttrib *value)
5479 {
5480     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5481     if (!clientExtensions.debug)
5482     {
5483         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5484         return false;
5485     }
5486 
5487     switch (attribute)
5488     {
5489         case EGL_DEBUG_MSG_CRITICAL_KHR:
5490         case EGL_DEBUG_MSG_ERROR_KHR:
5491         case EGL_DEBUG_MSG_WARN_KHR:
5492         case EGL_DEBUG_MSG_INFO_KHR:
5493         case EGL_DEBUG_CALLBACK_KHR:
5494             break;
5495 
5496         default:
5497             val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04X", attribute);
5498             return false;
5499     }
5500 
5501     return true;
5502 }
5503 
ValidateLabelObjectKHR(const ValidationContext * val,const Display * display,ObjectType objectType,EGLObjectKHR object,EGLLabelKHR label)5504 bool ValidateLabelObjectKHR(const ValidationContext *val,
5505                             const Display *display,
5506                             ObjectType objectType,
5507                             EGLObjectKHR object,
5508                             EGLLabelKHR label)
5509 {
5510     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5511     if (!clientExtensions.debug)
5512     {
5513         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5514         return false;
5515     }
5516 
5517     LabeledObject *labeledObject = nullptr;
5518     ANGLE_VALIDATION_TRY(ValidateLabeledObject(val, display, objectType, object, &labeledObject));
5519 
5520     return true;
5521 }
5522 
ValidateGetCompositorTimingSupportedANDROID(const ValidationContext * val,const Display * display,const Surface * surface,CompositorTiming name)5523 bool ValidateGetCompositorTimingSupportedANDROID(const ValidationContext *val,
5524                                                  const Display *display,
5525                                                  const Surface *surface,
5526                                                  CompositorTiming name)
5527 {
5528     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5529 
5530     if (!display->getExtensions().getFrameTimestamps)
5531     {
5532         val->setError(EGL_BAD_DISPLAY,
5533                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5534         return false;
5535     }
5536 
5537     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5538 
5539     if (!ValidCompositorTimingName(name))
5540     {
5541         val->setError(EGL_BAD_PARAMETER, "invalid timing name.");
5542         return false;
5543     }
5544 
5545     return true;
5546 }
5547 
ValidateGetCompositorTimingANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLint numTimestamps,const EGLint * names,const EGLnsecsANDROID * values)5548 bool ValidateGetCompositorTimingANDROID(const ValidationContext *val,
5549                                         const Display *display,
5550                                         const Surface *surface,
5551                                         EGLint numTimestamps,
5552                                         const EGLint *names,
5553                                         const EGLnsecsANDROID *values)
5554 {
5555     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5556 
5557     if (!display->getExtensions().getFrameTimestamps)
5558     {
5559         val->setError(EGL_BAD_DISPLAY,
5560                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5561         return false;
5562     }
5563 
5564     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5565 
5566     if (names == nullptr && numTimestamps > 0)
5567     {
5568         val->setError(EGL_BAD_PARAMETER, "names is NULL.");
5569         return false;
5570     }
5571 
5572     if (values == nullptr && numTimestamps > 0)
5573     {
5574         val->setError(EGL_BAD_PARAMETER, "values is NULL.");
5575         return false;
5576     }
5577 
5578     if (numTimestamps < 0)
5579     {
5580         val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
5581         return false;
5582     }
5583 
5584     for (EGLint i = 0; i < numTimestamps; i++)
5585     {
5586         CompositorTiming name = FromEGLenum<CompositorTiming>(names[i]);
5587 
5588         if (!ValidCompositorTimingName(name))
5589         {
5590             val->setError(EGL_BAD_PARAMETER, "invalid compositor timing.");
5591             return false;
5592         }
5593 
5594         if (!surface->getSupportedCompositorTimings().test(name))
5595         {
5596             val->setError(EGL_BAD_PARAMETER, "compositor timing not supported by surface.");
5597             return false;
5598         }
5599     }
5600 
5601     return true;
5602 }
5603 
ValidateGetNextFrameIdANDROID(const ValidationContext * val,const Display * display,const Surface * surface,const EGLuint64KHR * frameId)5604 bool ValidateGetNextFrameIdANDROID(const ValidationContext *val,
5605                                    const Display *display,
5606                                    const Surface *surface,
5607                                    const EGLuint64KHR *frameId)
5608 {
5609     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5610 
5611     if (!display->getExtensions().getFrameTimestamps)
5612     {
5613         val->setError(EGL_BAD_DISPLAY,
5614                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5615         return false;
5616     }
5617 
5618     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5619 
5620     if (frameId == nullptr)
5621     {
5622         val->setError(EGL_BAD_PARAMETER, "frameId is NULL.");
5623         return false;
5624     }
5625 
5626     return true;
5627 }
5628 
ValidateGetFrameTimestampSupportedANDROID(const ValidationContext * val,const Display * display,const Surface * surface,Timestamp timestamp)5629 bool ValidateGetFrameTimestampSupportedANDROID(const ValidationContext *val,
5630                                                const Display *display,
5631                                                const Surface *surface,
5632                                                Timestamp timestamp)
5633 {
5634     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5635 
5636     if (!display->getExtensions().getFrameTimestamps)
5637     {
5638         val->setError(EGL_BAD_DISPLAY,
5639                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5640         return false;
5641     }
5642 
5643     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5644 
5645     if (!ValidTimestampType(timestamp))
5646     {
5647         val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
5648         return false;
5649     }
5650 
5651     return true;
5652 }
5653 
ValidateGetFrameTimestampsANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,const EGLnsecsANDROID * values)5654 bool ValidateGetFrameTimestampsANDROID(const ValidationContext *val,
5655                                        const Display *display,
5656                                        const Surface *surface,
5657                                        EGLuint64KHR frameId,
5658                                        EGLint numTimestamps,
5659                                        const EGLint *timestamps,
5660                                        const EGLnsecsANDROID *values)
5661 {
5662     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5663 
5664     if (!display->getExtensions().getFrameTimestamps)
5665     {
5666         val->setError(EGL_BAD_DISPLAY,
5667                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5668         return false;
5669     }
5670 
5671     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5672 
5673     if (!surface->isTimestampsEnabled())
5674     {
5675         val->setError(EGL_BAD_SURFACE, "timestamp collection is not enabled for this surface.");
5676         return false;
5677     }
5678 
5679     if (timestamps == nullptr && numTimestamps > 0)
5680     {
5681         val->setError(EGL_BAD_PARAMETER, "timestamps is NULL.");
5682         return false;
5683     }
5684 
5685     if (values == nullptr && numTimestamps > 0)
5686     {
5687         val->setError(EGL_BAD_PARAMETER, "values is NULL.");
5688         return false;
5689     }
5690 
5691     if (numTimestamps < 0)
5692     {
5693         val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
5694         return false;
5695     }
5696 
5697     for (EGLint i = 0; i < numTimestamps; i++)
5698     {
5699         Timestamp timestamp = FromEGLenum<Timestamp>(timestamps[i]);
5700 
5701         if (!ValidTimestampType(timestamp))
5702         {
5703             val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
5704             return false;
5705         }
5706 
5707         if (!surface->getSupportedTimestamps().test(timestamp))
5708         {
5709             val->setError(EGL_BAD_PARAMETER, "timestamp not supported by surface.");
5710             return false;
5711         }
5712     }
5713 
5714     return true;
5715 }
5716 
ValidateQueryStringiANGLE(const ValidationContext * val,const Display * display,EGLint name,EGLint index)5717 bool ValidateQueryStringiANGLE(const ValidationContext *val,
5718                                const Display *display,
5719                                EGLint name,
5720                                EGLint index)
5721 {
5722     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5723 
5724     if (!Display::GetClientExtensions().featureControlANGLE)
5725     {
5726         val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_feature_control extension is not available.");
5727         return false;
5728     }
5729 
5730     if (index < 0)
5731     {
5732         val->setError(EGL_BAD_PARAMETER, "index is negative.");
5733         return false;
5734     }
5735 
5736     switch (name)
5737     {
5738         case EGL_FEATURE_NAME_ANGLE:
5739         case EGL_FEATURE_CATEGORY_ANGLE:
5740         case EGL_FEATURE_DESCRIPTION_ANGLE:
5741         case EGL_FEATURE_BUG_ANGLE:
5742         case EGL_FEATURE_STATUS_ANGLE:
5743         case EGL_FEATURE_CONDITION_ANGLE:
5744             break;
5745         default:
5746             val->setError(EGL_BAD_PARAMETER, "name is not valid.");
5747             return false;
5748     }
5749 
5750     if (static_cast<size_t>(index) >= display->getFeatures().size())
5751     {
5752         val->setError(EGL_BAD_PARAMETER, "index is too big.");
5753         return false;
5754     }
5755 
5756     return true;
5757 }
5758 
ValidateQueryDisplayAttribEXT(const ValidationContext * val,const Display * display,const EGLint attribute,const EGLAttrib * value)5759 bool ValidateQueryDisplayAttribEXT(const ValidationContext *val,
5760                                    const Display *display,
5761                                    const EGLint attribute,
5762                                    const EGLAttrib *value)
5763 {
5764     ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
5765     return true;
5766 }
5767 
ValidateQueryDisplayAttribANGLE(const ValidationContext * val,const Display * display,const EGLint attribute,const EGLAttrib * value)5768 bool ValidateQueryDisplayAttribANGLE(const ValidationContext *val,
5769                                      const Display *display,
5770                                      const EGLint attribute,
5771                                      const EGLAttrib *value)
5772 {
5773     ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
5774     return true;
5775 }
5776 
ValidateGetNativeClientBufferANDROID(const ValidationContext * val,const AHardwareBuffer * buffer)5777 bool ValidateGetNativeClientBufferANDROID(const ValidationContext *val,
5778                                           const AHardwareBuffer *buffer)
5779 {
5780     // No extension check is done because no display is passed to eglGetNativeClientBufferANDROID
5781     // despite it being a display extension.  No display is needed for the implementation though.
5782     if (buffer == nullptr)
5783     {
5784         val->setError(EGL_BAD_PARAMETER, "NULL buffer.");
5785         return false;
5786     }
5787 
5788     return true;
5789 }
5790 
ValidateCreateNativeClientBufferANDROID(const ValidationContext * val,const egl::AttributeMap & attribMap)5791 bool ValidateCreateNativeClientBufferANDROID(const ValidationContext *val,
5792                                              const egl::AttributeMap &attribMap)
5793 {
5794     attribMap.initializeWithoutValidation();
5795 
5796     if (attribMap.isEmpty() || attribMap.begin()->second == EGL_NONE)
5797     {
5798         val->setError(EGL_BAD_PARAMETER, "invalid attribute list.");
5799         return false;
5800     }
5801 
5802     int width     = attribMap.getAsInt(EGL_WIDTH, 0);
5803     int height    = attribMap.getAsInt(EGL_HEIGHT, 0);
5804     int redSize   = attribMap.getAsInt(EGL_RED_SIZE, 0);
5805     int greenSize = attribMap.getAsInt(EGL_GREEN_SIZE, 0);
5806     int blueSize  = attribMap.getAsInt(EGL_BLUE_SIZE, 0);
5807     int alphaSize = attribMap.getAsInt(EGL_ALPHA_SIZE, 0);
5808     int usage     = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
5809 
5810     for (AttributeMap::const_iterator attributeIter = attribMap.begin();
5811          attributeIter != attribMap.end(); attributeIter++)
5812     {
5813         EGLAttrib attribute = attributeIter->first;
5814         switch (attribute)
5815         {
5816             case EGL_WIDTH:
5817             case EGL_HEIGHT:
5818                 // Validation done after the switch statement
5819                 break;
5820             case EGL_RED_SIZE:
5821             case EGL_GREEN_SIZE:
5822             case EGL_BLUE_SIZE:
5823             case EGL_ALPHA_SIZE:
5824                 if (redSize < 0 || greenSize < 0 || blueSize < 0 || alphaSize < 0)
5825                 {
5826                     val->setError(EGL_BAD_PARAMETER, "incorrect channel size requested");
5827                     return false;
5828                 }
5829                 break;
5830             case EGL_NATIVE_BUFFER_USAGE_ANDROID:
5831                 // The buffer must be used for either a texture or a renderbuffer.
5832                 if ((usage & ~(EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID |
5833                                EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID |
5834                                EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) != 0)
5835                 {
5836                     val->setError(EGL_BAD_PARAMETER, "invalid usage flag");
5837                     return false;
5838                 }
5839                 break;
5840             case EGL_NONE:
5841                 break;
5842             default:
5843                 val->setError(EGL_BAD_ATTRIBUTE, "invalid attribute");
5844                 return false;
5845         }
5846     }
5847 
5848     // Validate EGL_WIDTH and EGL_HEIGHT values passed in. Done here to account
5849     // for the case where EGL_WIDTH and EGL_HEIGHT were not part of the attribute list.
5850     if (width <= 0 || height <= 0)
5851     {
5852         val->setError(EGL_BAD_PARAMETER, "incorrect buffer dimensions requested");
5853         return false;
5854     }
5855 
5856     if (gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap) == 0)
5857     {
5858         val->setError(EGL_BAD_PARAMETER, "unsupported format");
5859         return false;
5860     }
5861     return true;
5862 }
5863 
ValidateDupNativeFenceFDANDROID(const ValidationContext * val,const Display * display,const Sync * sync)5864 bool ValidateDupNativeFenceFDANDROID(const ValidationContext *val,
5865                                      const Display *display,
5866                                      const Sync *sync)
5867 {
5868     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5869 
5870     if (!display->getExtensions().nativeFenceSyncANDROID)
5871     {
5872         val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_native_fence_sync extension is not available.");
5873         return false;
5874     }
5875 
5876     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
5877 
5878     return true;
5879 }
5880 
ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext * val,const Display * display,const Surface * surface,EGLFrameTokenANGLE frametoken)5881 bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val,
5882                                             const Display *display,
5883                                             const Surface *surface,
5884                                             EGLFrameTokenANGLE frametoken)
5885 {
5886     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5887 
5888     if (!display->getExtensions().swapWithFrameToken)
5889     {
5890         val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_swap_buffers_with_frame_token is not available.");
5891         return false;
5892     }
5893 
5894     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5895 
5896     return true;
5897 }
5898 
ValidateSignalSyncKHR(const ValidationContext * val,const Display * display,const Sync * sync,EGLenum mode)5899 bool ValidateSignalSyncKHR(const ValidationContext *val,
5900                            const Display *display,
5901                            const Sync *sync,
5902                            EGLenum mode)
5903 {
5904     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5905 
5906     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
5907 
5908     if (sync->getType() == EGL_SYNC_REUSABLE_KHR)
5909     {
5910         if (!display->getExtensions().reusableSyncKHR)
5911         {
5912             val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
5913             return false;
5914         }
5915 
5916         if ((mode != EGL_SIGNALED_KHR) && (mode != EGL_UNSIGNALED_KHR))
5917         {
5918             val->setError(EGL_BAD_PARAMETER, "eglSignalSyncKHR invalid mode.");
5919             return false;
5920         }
5921 
5922         return true;
5923     }
5924 
5925     val->setError(EGL_BAD_MATCH);
5926     return false;
5927 }
5928 
ValidateQuerySurfacePointerANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface,EGLint attribute,void * const * value)5929 bool ValidateQuerySurfacePointerANGLE(const ValidationContext *val,
5930                                       const Display *display,
5931                                       const Surface *eglSurface,
5932                                       EGLint attribute,
5933                                       void *const *value)
5934 {
5935     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5936 
5937     if (!display->getExtensions().querySurfacePointer)
5938     {
5939         val->setError(EGL_BAD_ACCESS);
5940         return false;
5941     }
5942 
5943     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
5944 
5945     // validate the attribute parameter
5946     switch (attribute)
5947     {
5948         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
5949             if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
5950             {
5951                 val->setError(EGL_BAD_ATTRIBUTE);
5952                 return false;
5953             }
5954             break;
5955         case EGL_DXGI_KEYED_MUTEX_ANGLE:
5956             if (!display->getExtensions().keyedMutex)
5957             {
5958                 val->setError(EGL_BAD_ATTRIBUTE);
5959                 return false;
5960             }
5961             break;
5962         default:
5963             val->setError(EGL_BAD_ATTRIBUTE);
5964             return false;
5965     }
5966 
5967     return true;
5968 }
5969 
ValidatePostSubBufferNV(const ValidationContext * val,const Display * display,const Surface * eglSurface,EGLint x,EGLint y,EGLint width,EGLint height)5970 bool ValidatePostSubBufferNV(const ValidationContext *val,
5971                              const Display *display,
5972                              const Surface *eglSurface,
5973                              EGLint x,
5974                              EGLint y,
5975                              EGLint width,
5976                              EGLint height)
5977 {
5978     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5979 
5980     if (!display->getExtensions().postSubBuffer)
5981     {
5982         val->setError(EGL_BAD_ACCESS);
5983         return false;
5984     }
5985 
5986     if (x < 0 || y < 0 || width < 0 || height < 0)
5987     {
5988         val->setError(EGL_BAD_PARAMETER);
5989         return false;
5990     }
5991 
5992     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
5993 
5994     if (display->isDeviceLost())
5995     {
5996         val->setError(EGL_CONTEXT_LOST);
5997         return false;
5998     }
5999 
6000     return true;
6001 }
6002 
ValidateQueryDeviceAttribEXT(const ValidationContext * val,const Device * device,EGLint attribute,const EGLAttrib * value)6003 bool ValidateQueryDeviceAttribEXT(const ValidationContext *val,
6004                                   const Device *device,
6005                                   EGLint attribute,
6006                                   const EGLAttrib *value)
6007 {
6008     ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
6009 
6010     if (!Display::GetClientExtensions().deviceQueryEXT)
6011     {
6012         val->setError(EGL_BAD_ACCESS, "EGL_EXT_device_query not supported.");
6013         return false;
6014     }
6015 
6016     // validate the attribute parameter
6017     switch (attribute)
6018     {
6019         case EGL_D3D11_DEVICE_ANGLE:
6020         case EGL_D3D9_DEVICE_ANGLE:
6021             if (!device->getExtensions().deviceD3D || device->getType() != attribute)
6022             {
6023                 val->setError(EGL_BAD_ATTRIBUTE);
6024                 return false;
6025             }
6026             break;
6027         case EGL_EAGL_CONTEXT_ANGLE:
6028             if (!device->getExtensions().deviceEAGL)
6029             {
6030                 val->setError(EGL_BAD_ATTRIBUTE);
6031                 return false;
6032             }
6033             break;
6034         case EGL_METAL_DEVICE_ANGLE:
6035             if (!device->getExtensions().deviceMetal)
6036             {
6037                 val->setError(EGL_BAD_ATTRIBUTE);
6038                 return false;
6039             }
6040             break;
6041         case EGL_VULKAN_VERSION_ANGLE:
6042         case EGL_VULKAN_INSTANCE_ANGLE:
6043         case EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE:
6044         case EGL_VULKAN_PHYSICAL_DEVICE_ANGLE:
6045         case EGL_VULKAN_DEVICE_ANGLE:
6046         case EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE:
6047         case EGL_VULKAN_FEATURES_ANGLE:
6048         case EGL_VULKAN_QUEUE_ANGLE:
6049         case EGL_VULKAN_QUEUE_FAMILIY_INDEX_ANGLE:
6050         case EGL_VULKAN_GET_INSTANCE_PROC_ADDR:
6051             if (!device->getExtensions().deviceVulkan)
6052             {
6053                 val->setError(EGL_BAD_ATTRIBUTE);
6054                 return false;
6055             }
6056             break;
6057         case EGL_CGL_CONTEXT_ANGLE:
6058         case EGL_CGL_PIXEL_FORMAT_ANGLE:
6059             if (!device->getExtensions().deviceCGL)
6060             {
6061                 val->setError(EGL_BAD_ATTRIBUTE);
6062                 return false;
6063             }
6064             break;
6065         default:
6066             val->setError(EGL_BAD_ATTRIBUTE);
6067             return false;
6068     }
6069     return true;
6070 }
6071 
ValidateQueryDeviceStringEXT(const ValidationContext * val,const Device * device,EGLint name)6072 bool ValidateQueryDeviceStringEXT(const ValidationContext *val, const Device *device, EGLint name)
6073 {
6074     ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
6075     return true;
6076 }
6077 
ValidateReleaseHighPowerGPUANGLE(const ValidationContext * val,const Display * display,const gl::Context * context)6078 bool ValidateReleaseHighPowerGPUANGLE(const ValidationContext *val,
6079                                       const Display *display,
6080                                       const gl::Context *context)
6081 {
6082     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
6083     return true;
6084 }
6085 
ValidateReacquireHighPowerGPUANGLE(const ValidationContext * val,const Display * display,const gl::Context * context)6086 bool ValidateReacquireHighPowerGPUANGLE(const ValidationContext *val,
6087                                         const Display *display,
6088                                         const gl::Context *context)
6089 {
6090     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
6091     return true;
6092 }
6093 
ValidateHandleGPUSwitchANGLE(const ValidationContext * val,const Display * display)6094 bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const Display *display)
6095 {
6096     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6097     return true;
6098 }
6099 
ValidateGetCurrentDisplay(const ValidationContext * val)6100 bool ValidateGetCurrentDisplay(const ValidationContext *val)
6101 {
6102     return true;
6103 }
6104 
ValidateGetCurrentSurface(const ValidationContext * val,EGLint readdraw)6105 bool ValidateGetCurrentSurface(const ValidationContext *val, EGLint readdraw)
6106 {
6107     return true;
6108 }
6109 
ValidateGetDisplay(const ValidationContext * val,EGLNativeDisplayType display_id)6110 bool ValidateGetDisplay(const ValidationContext *val, EGLNativeDisplayType display_id)
6111 {
6112     return true;
6113 }
6114 
ValidateGetError(const ValidationContext * val)6115 bool ValidateGetError(const ValidationContext *val)
6116 {
6117     return true;
6118 }
6119 
ValidateGetProcAddress(const ValidationContext * val,const char * procname)6120 bool ValidateGetProcAddress(const ValidationContext *val, const char *procname)
6121 {
6122     return true;
6123 }
6124 
ValidateQueryString(const ValidationContext * val,const Display * dpyPacked,EGLint name)6125 bool ValidateQueryString(const ValidationContext *val, const Display *dpyPacked, EGLint name)
6126 {
6127     if (name != EGL_EXTENSIONS || dpyPacked != nullptr)
6128     {
6129         ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpyPacked));
6130     }
6131 
6132     switch (name)
6133     {
6134         case EGL_CLIENT_APIS:
6135         case EGL_EXTENSIONS:
6136         case EGL_VENDOR:
6137         case EGL_VERSION:
6138             break;
6139         default:
6140             val->setError(EGL_BAD_PARAMETER);
6141             return false;
6142     }
6143     return true;
6144 }
6145 
ValidateWaitGL(const ValidationContext * val)6146 bool ValidateWaitGL(const ValidationContext *val)
6147 {
6148     if (val->eglThread->getDisplay() == nullptr)
6149     {
6150         // EGL spec says this about eglWaitGL -
6151         //    eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
6152         return true;
6153     }
6154 
6155     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
6156     return true;
6157 }
6158 
ValidateQueryAPI(const ValidationContext * val)6159 bool ValidateQueryAPI(const ValidationContext *val)
6160 {
6161     return true;
6162 }
6163 
ValidateReleaseThread(const ValidationContext * val)6164 bool ValidateReleaseThread(const ValidationContext *val)
6165 {
6166     return true;
6167 }
6168 
ValidateWaitClient(const ValidationContext * val)6169 bool ValidateWaitClient(const ValidationContext *val)
6170 {
6171     if (val->eglThread->getDisplay() == nullptr)
6172     {
6173         // EGL spec says this about eglWaitClient -
6174         //    If there is no current context for the current rendering API,
6175         //    the function has no effect but still returns EGL_TRUE.
6176         return true;
6177     }
6178 
6179     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
6180     return true;
6181 }
6182 
ValidateGetCurrentContext(const ValidationContext * val)6183 bool ValidateGetCurrentContext(const ValidationContext *val)
6184 {
6185     return true;
6186 }
6187 
ValidateCreatePlatformPixmapSurface(const ValidationContext * val,const Display * dpyPacked,const Config * configPacked,const void * native_pixmap,const AttributeMap & attrib_listPacked)6188 bool ValidateCreatePlatformPixmapSurface(const ValidationContext *val,
6189                                          const Display *dpyPacked,
6190                                          const Config *configPacked,
6191                                          const void *native_pixmap,
6192                                          const AttributeMap &attrib_listPacked)
6193 {
6194     EGLNativePixmapType nativePixmap =
6195         reinterpret_cast<EGLNativePixmapType>(const_cast<void *>(native_pixmap));
6196     return ValidateCreatePixmapSurface(val, dpyPacked, configPacked, nativePixmap,
6197                                        attrib_listPacked);
6198 }
6199 
ValidateCreatePlatformWindowSurface(const ValidationContext * val,const Display * dpyPacked,const Config * configPacked,const void * native_window,const AttributeMap & attrib_listPacked)6200 bool ValidateCreatePlatformWindowSurface(const ValidationContext *val,
6201                                          const Display *dpyPacked,
6202                                          const Config *configPacked,
6203                                          const void *native_window,
6204                                          const AttributeMap &attrib_listPacked)
6205 {
6206     EGLNativeWindowType nativeWindow =
6207         reinterpret_cast<EGLNativeWindowType>(const_cast<void *>(native_window));
6208     return ValidateCreateWindowSurface(val, dpyPacked, configPacked, nativeWindow,
6209                                        attrib_listPacked);
6210 }
6211 
ValidateLockSurfaceKHR(const ValidationContext * val,const egl::Display * dpy,const Surface * surface,const AttributeMap & attributes)6212 bool ValidateLockSurfaceKHR(const ValidationContext *val,
6213                             const egl::Display *dpy,
6214                             const Surface *surface,
6215                             const AttributeMap &attributes)
6216 {
6217     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6218     ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
6219 
6220     if (!dpy->getExtensions().lockSurface3KHR)
6221     {
6222         val->setError(EGL_BAD_ACCESS);
6223         return false;
6224     }
6225 
6226     if (surface->isLocked())
6227     {
6228         val->setError(EGL_BAD_ACCESS);
6229         return false;
6230     }
6231 
6232     if ((surface->getConfig()->surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == false)
6233     {
6234         val->setError(EGL_BAD_ACCESS, "Config does not support EGL_LOCK_SURFACE_BIT");
6235         return false;
6236     }
6237 
6238     if (surface->isCurrentOnAnyContext())
6239     {
6240         val->setError(EGL_BAD_ACCESS,
6241                       "Surface cannot be current to a context for eglLockSurface()");
6242         return false;
6243     }
6244 
6245     if (surface->hasProtectedContent())
6246     {
6247         val->setError(EGL_BAD_ACCESS, "Surface cannot be protected content for eglLockSurface()");
6248         return false;
6249     }
6250 
6251     attributes.initializeWithoutValidation();
6252 
6253     for (const auto &attributeIter : attributes)
6254     {
6255         EGLAttrib attribute = attributeIter.first;
6256         EGLAttrib value     = attributeIter.second;
6257 
6258         switch (attribute)
6259         {
6260             case EGL_MAP_PRESERVE_PIXELS_KHR:
6261                 if (!((value == EGL_FALSE) || (value == EGL_TRUE)))
6262                 {
6263                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_MAP_PRESERVE_PIXELS_KHR value");
6264                     return false;
6265                 }
6266                 break;
6267             case EGL_LOCK_USAGE_HINT_KHR:
6268                 if ((value & (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR)) != value)
6269                 {
6270                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_LOCK_USAGE_HINT_KHR value");
6271                     return false;
6272                 }
6273                 break;
6274             default:
6275                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid query surface64 attribute");
6276                 return false;
6277         }
6278     }
6279 
6280     return true;
6281 }
6282 
ValidateQuerySurface64KHR(const ValidationContext * val,const egl::Display * dpy,const Surface * surface,EGLint attribute,const EGLAttribKHR * value)6283 bool ValidateQuerySurface64KHR(const ValidationContext *val,
6284                                const egl::Display *dpy,
6285                                const Surface *surface,
6286                                EGLint attribute,
6287                                const EGLAttribKHR *value)
6288 {
6289     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6290     ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
6291 
6292     if (!dpy->getExtensions().lockSurface3KHR)
6293     {
6294         val->setError(EGL_BAD_ACCESS);
6295         return false;
6296     }
6297 
6298     switch (attribute)
6299     {
6300         case EGL_BITMAP_PITCH_KHR:
6301         case EGL_BITMAP_ORIGIN_KHR:
6302         case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
6303         case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
6304         case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
6305         case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
6306         case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
6307         case EGL_BITMAP_PIXEL_SIZE_KHR:
6308         case EGL_BITMAP_POINTER_KHR:
6309             break;
6310         default:
6311             val->setError(EGL_BAD_ATTRIBUTE, "Invalid eglQuerySurface64 attribute");
6312             return false;
6313     }
6314 
6315     if (value == nullptr)
6316     {
6317         val->setError(EGL_BAD_PARAMETER, "value is NULL.");
6318         return false;
6319     }
6320 
6321     if (!surface->isLocked())
6322     {
6323         val->setError(EGL_BAD_ACCESS, "Surface is not locked");
6324         return false;
6325     }
6326 
6327     return true;
6328 }
6329 
ValidateUnlockSurfaceKHR(const ValidationContext * val,const egl::Display * dpy,const Surface * surface)6330 bool ValidateUnlockSurfaceKHR(const ValidationContext *val,
6331                               const egl::Display *dpy,
6332                               const Surface *surface)
6333 {
6334     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6335     ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
6336 
6337     if (!dpy->getExtensions().lockSurface3KHR)
6338     {
6339         val->setError(EGL_BAD_ACCESS);
6340         return false;
6341     }
6342 
6343     if (!surface->isLocked())
6344     {
6345         val->setError(EGL_BAD_PARAMETER, "Surface is not locked.");
6346         return false;
6347     }
6348 
6349     return true;
6350 }
6351 
ValidateExportVkImageANGLE(const ValidationContext * val,const Display * dpy,const Image * image,const void * vkImage,const void * vkImageCreateInfo)6352 bool ValidateExportVkImageANGLE(const ValidationContext *val,
6353                                 const Display *dpy,
6354                                 const Image *image,
6355                                 const void *vkImage,
6356                                 const void *vkImageCreateInfo)
6357 {
6358     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6359     ANGLE_VALIDATION_TRY(ValidateImage(val, dpy, image));
6360 
6361     if (!dpy->getExtensions().vulkanImageANGLE)
6362     {
6363         val->setError(EGL_BAD_ACCESS);
6364         return false;
6365     }
6366 
6367     if (!vkImage)
6368     {
6369         val->setError(EGL_BAD_PARAMETER, "Output VkImage pointer is null.");
6370         return false;
6371     }
6372 
6373     if (!vkImageCreateInfo)
6374     {
6375         val->setError(EGL_BAD_PARAMETER, "Output VkImageCreateInfo pointer is null.");
6376         return false;
6377     }
6378 
6379     return true;
6380 }
6381 
6382 }  // namespace egl
6383