• 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.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 EGLAttrib attribute,const EGLAttrib value,const DisplayExtensions & extensions)101 Error ValidateStreamAttribute(const EGLAttrib attribute,
102                               const EGLAttrib value,
103                               const DisplayExtensions &extensions)
104 {
105     switch (attribute)
106     {
107         case EGL_STREAM_STATE_KHR:
108         case EGL_PRODUCER_FRAME_KHR:
109         case EGL_CONSUMER_FRAME_KHR:
110             return EglBadAccess() << "Attempt to initialize readonly parameter";
111         case EGL_CONSUMER_LATENCY_USEC_KHR:
112             // Technically not in spec but a latency < 0 makes no sense so we check it
113             if (value < 0)
114             {
115                 return EglBadParameter() << "Latency must be positive";
116             }
117             break;
118         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
119             if (!extensions.streamConsumerGLTexture)
120             {
121                 return EglBadAttribute() << "Consumer GL extension not enabled";
122             }
123             // Again not in spec but it should be positive anyways
124             if (value < 0)
125             {
126                 return EglBadParameter() << "Timeout must be positive";
127             }
128             break;
129         default:
130             return EglBadAttribute() << "Invalid stream attribute";
131     }
132     return NoError();
133 }
134 
ValidateCreateImageMipLevelCommon(gl::Context * context,const gl::Texture * texture,EGLAttrib level)135 Error ValidateCreateImageMipLevelCommon(gl::Context *context,
136                                         const gl::Texture *texture,
137                                         EGLAttrib level)
138 {
139     // Note that the spec EGL_create_image spec does not explicitly specify an error
140     // when the level is outside the base/max level range, but it does mention that the
141     // level "must be a part of the complete texture object <buffer>". It can be argued
142     // that out-of-range levels are not a part of the complete texture.
143     const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
144     if (level > 0 &&
145         (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
146          static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
147     {
148         return EglBadParameter() << "texture must be complete if level is non-zero.";
149     }
150 
151     if (level == 0 && !texture->isMipmapComplete() &&
152         TextureHasNonZeroMipLevelsSpecified(context, texture))
153     {
154         return EglBadParameter() << "if level is zero and the texture is incomplete, it must "
155                                     "have no mip levels specified except zero.";
156     }
157 
158     return NoError();
159 }
160 
ValidateConfigAttribute(const Display * display,EGLAttrib attribute)161 Error ValidateConfigAttribute(const Display *display, EGLAttrib attribute)
162 {
163     switch (attribute)
164     {
165         case EGL_BUFFER_SIZE:
166         case EGL_ALPHA_SIZE:
167         case EGL_BLUE_SIZE:
168         case EGL_GREEN_SIZE:
169         case EGL_RED_SIZE:
170         case EGL_DEPTH_SIZE:
171         case EGL_STENCIL_SIZE:
172         case EGL_CONFIG_CAVEAT:
173         case EGL_CONFIG_ID:
174         case EGL_LEVEL:
175         case EGL_NATIVE_RENDERABLE:
176         case EGL_NATIVE_VISUAL_ID:
177         case EGL_NATIVE_VISUAL_TYPE:
178         case EGL_SAMPLES:
179         case EGL_SAMPLE_BUFFERS:
180         case EGL_SURFACE_TYPE:
181         case EGL_TRANSPARENT_TYPE:
182         case EGL_TRANSPARENT_BLUE_VALUE:
183         case EGL_TRANSPARENT_GREEN_VALUE:
184         case EGL_TRANSPARENT_RED_VALUE:
185         case EGL_BIND_TO_TEXTURE_RGB:
186         case EGL_BIND_TO_TEXTURE_RGBA:
187         case EGL_MIN_SWAP_INTERVAL:
188         case EGL_MAX_SWAP_INTERVAL:
189         case EGL_LUMINANCE_SIZE:
190         case EGL_ALPHA_MASK_SIZE:
191         case EGL_COLOR_BUFFER_TYPE:
192         case EGL_RENDERABLE_TYPE:
193         case EGL_MATCH_NATIVE_PIXMAP:
194         case EGL_CONFORMANT:
195         case EGL_MAX_PBUFFER_WIDTH:
196         case EGL_MAX_PBUFFER_HEIGHT:
197         case EGL_MAX_PBUFFER_PIXELS:
198             break;
199 
200         case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
201             if (!display->getExtensions().surfaceOrientation)
202             {
203                 return EglBadAttribute() << "EGL_ANGLE_surface_orientation is not enabled.";
204             }
205             break;
206 
207         case EGL_COLOR_COMPONENT_TYPE_EXT:
208             if (!display->getExtensions().pixelFormatFloat)
209             {
210                 return EglBadAttribute() << "EGL_EXT_pixel_format_float is not enabled.";
211             }
212             break;
213 
214         case EGL_RECORDABLE_ANDROID:
215             if (!display->getExtensions().recordable)
216             {
217                 return EglBadAttribute() << "EGL_ANDROID_recordable is not enabled.";
218             }
219             break;
220 
221         case EGL_FRAMEBUFFER_TARGET_ANDROID:
222             if (!display->getExtensions().framebufferTargetANDROID)
223             {
224                 return EglBadAttribute() << "EGL_ANDROID_framebuffer_target is not enabled.";
225             }
226             break;
227 
228         case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
229             if (!display->getExtensions().iosurfaceClientBuffer)
230             {
231                 return EglBadAttribute() << "EGL_ANGLE_iosurface_client_buffer is not enabled.";
232             }
233             break;
234 
235         default:
236             return EglBadAttribute() << "Unknown attribute.";
237     }
238 
239     return NoError();
240 }
241 
ValidateConfigAttributeValue(const Display * display,EGLAttrib attribute,EGLAttrib value)242 Error ValidateConfigAttributeValue(const Display *display, EGLAttrib attribute, EGLAttrib value)
243 {
244     switch (attribute)
245     {
246 
247         case EGL_BIND_TO_TEXTURE_RGB:
248         case EGL_BIND_TO_TEXTURE_RGBA:
249             switch (value)
250             {
251                 case EGL_DONT_CARE:
252                 case EGL_TRUE:
253                 case EGL_FALSE:
254                     break;
255                 default:
256                     return EglBadAttribute() << "EGL_bind_to_texture invalid attribute: " << value;
257             }
258             break;
259 
260         case EGL_COLOR_BUFFER_TYPE:
261             switch (value)
262             {
263                 case EGL_RGB_BUFFER:
264                 case EGL_LUMINANCE_BUFFER:
265                 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
266                 case EGL_DONT_CARE:
267                     break;
268                 default:
269                     return EglBadAttribute()
270                            << "EGL_color_buffer_type invalid attribute: " << value;
271             }
272             break;
273 
274         case EGL_NATIVE_RENDERABLE:
275             switch (value)
276             {
277                 case EGL_DONT_CARE:
278                 case EGL_TRUE:
279                 case EGL_FALSE:
280                     break;
281                 default:
282                     return EglBadAttribute()
283                            << "EGL_native_renderable invalid attribute: " << value;
284             }
285             break;
286 
287         case EGL_TRANSPARENT_TYPE:
288             switch (value)
289             {
290                 case EGL_NONE:
291                 case EGL_TRANSPARENT_RGB:
292                 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
293                 case EGL_DONT_CARE:
294                     break;
295                 default:
296                     return EglBadAttribute() << "EGL_transparent_type invalid attribute: " << value;
297             }
298             break;
299 
300         case EGL_RECORDABLE_ANDROID:
301             switch (value)
302             {
303                 case EGL_TRUE:
304                 case EGL_FALSE:
305                 case EGL_DONT_CARE:
306                     break;
307                 default:
308                     return EglBadAttribute()
309                            << "EGL_RECORDABLE_ANDROID invalid attribute: " << value;
310             }
311             break;
312 
313         case EGL_COLOR_COMPONENT_TYPE_EXT:
314             switch (value)
315             {
316                 case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:
317                 case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:
318                 case EGL_DONT_CARE:
319                     break;
320                 default:
321                     return EglBadAttribute()
322                            << "EGL_COLOR_COMPONENT_TYPE_EXT invalid attribute: " << value;
323             }
324             break;
325 
326         default:
327             break;
328     }
329 
330     return NoError();
331 }
332 
ValidateConfigAttributes(const Display * display,const AttributeMap & attributes)333 Error ValidateConfigAttributes(const Display *display, const AttributeMap &attributes)
334 {
335     for (const auto &attrib : attributes)
336     {
337         ANGLE_TRY(ValidateConfigAttribute(display, attrib.first));
338         ANGLE_TRY(ValidateConfigAttributeValue(display, attrib.first, attrib.second));
339     }
340 
341     return NoError();
342 }
343 
ValidateColorspaceAttribute(const DisplayExtensions & displayExtensions,EGLAttrib colorSpace)344 Error ValidateColorspaceAttribute(const DisplayExtensions &displayExtensions, EGLAttrib colorSpace)
345 {
346     switch (colorSpace)
347     {
348         case EGL_GL_COLORSPACE_SRGB:
349             break;
350         case EGL_GL_COLORSPACE_LINEAR:
351             break;
352         case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
353             if (!displayExtensions.glColorspaceDisplayP3Linear)
354             {
355                 return EglBadAttribute() << "EXT_gl_colorspace_display_p3_linear is not available.";
356             }
357             break;
358         case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
359             if (!displayExtensions.glColorspaceDisplayP3)
360             {
361                 return EglBadAttribute() << "EXT_gl_colorspace_display_p3 is not available.";
362             }
363             break;
364         case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
365             if (!displayExtensions.glColorspaceDisplayP3Passthrough)
366             {
367                 return EglBadAttribute()
368                        << "EGL_EXT_gl_colorspace_display_p3_passthrough is not available.";
369             }
370             break;
371         case EGL_GL_COLORSPACE_SCRGB_EXT:
372             if (!displayExtensions.glColorspaceScrgb)
373             {
374                 return EglBadAttribute() << "EXT_gl_colorspace_scrgb is not available.";
375             }
376             break;
377         case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
378             if (!displayExtensions.glColorspaceScrgbLinear)
379             {
380                 return EglBadAttribute() << "EXT_gl_colorspace_scrgb_linear is not available.";
381             }
382             break;
383         default:
384             return EglBadAttribute();
385     }
386     return NoError();
387 }
ValidatePlatformType(const ClientExtensions & clientExtensions,EGLAttrib platformType)388 Error ValidatePlatformType(const ClientExtensions &clientExtensions, EGLAttrib platformType)
389 {
390     switch (platformType)
391     {
392         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
393             break;
394 
395         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
396         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
397             if (!clientExtensions.platformANGLED3D)
398             {
399                 return EglBadAttribute() << "Direct3D platform is unsupported.";
400             }
401             break;
402 
403         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
404         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
405             if (!clientExtensions.platformANGLEOpenGL)
406             {
407                 return EglBadAttribute() << "OpenGL platform is unsupported.";
408             }
409             break;
410 
411         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
412             if (!clientExtensions.platformANGLENULL)
413             {
414                 return EglBadAttribute() << "Display type EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
415                                             "requires EGL_ANGLE_platform_angle_null.";
416             }
417             break;
418 
419         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
420             if (!clientExtensions.platformANGLEVulkan)
421             {
422                 return EglBadAttribute() << "Vulkan platform is unsupported.";
423             }
424             break;
425 
426         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
427             if (!clientExtensions.platformANGLEMetal)
428             {
429                 return EglBadAttribute() << "Metal platform is unsupported.";
430             }
431             break;
432 
433         default:
434             return EglBadAttribute() << "Unknown platform type.";
435     }
436 
437     return NoError();
438 }
439 
ValidateGetPlatformDisplayCommon(EGLenum platform,void * native_display,const AttributeMap & attribMap)440 Error ValidateGetPlatformDisplayCommon(EGLenum platform,
441                                        void *native_display,
442                                        const AttributeMap &attribMap)
443 {
444     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
445 
446     switch (platform)
447     {
448         case EGL_PLATFORM_ANGLE_ANGLE:
449             if (!clientExtensions.platformANGLE)
450             {
451                 return EglBadParameter() << "Platform ANGLE extension is not active";
452             }
453             break;
454         case EGL_PLATFORM_DEVICE_EXT:
455             if (!clientExtensions.platformDevice)
456             {
457                 return EglBadParameter() << "Platform Device extension is not active";
458             }
459             break;
460         default:
461             return EglBadConfig() << "Bad platform type.";
462     }
463 
464     if (platform == EGL_PLATFORM_ANGLE_ANGLE)
465     {
466         EGLAttrib platformType       = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
467         bool enableAutoTrimSpecified = false;
468         bool enableD3D11on12         = false;
469         bool presentPathSpecified    = false;
470         bool luidSpecified           = false;
471 
472         Optional<EGLAttrib> majorVersion;
473         Optional<EGLAttrib> minorVersion;
474         Optional<EGLAttrib> deviceType;
475         Optional<EGLAttrib> eglHandle;
476 
477         for (const auto &curAttrib : attribMap)
478         {
479             const EGLAttrib value = curAttrib.second;
480 
481             switch (curAttrib.first)
482             {
483                 case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
484                 {
485                     ANGLE_TRY(ValidatePlatformType(clientExtensions, value));
486                     platformType = value;
487                     break;
488                 }
489 
490                 case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
491                     if (value != EGL_DONT_CARE)
492                     {
493                         majorVersion = value;
494                     }
495                     break;
496 
497                 case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
498                     if (value != EGL_DONT_CARE)
499                     {
500                         minorVersion = value;
501                     }
502                     break;
503 
504                 case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
505                     switch (value)
506                     {
507                         case EGL_TRUE:
508                         case EGL_FALSE:
509                             break;
510                         default:
511                             return EglBadAttribute() << "Invalid automatic trim attribute";
512                     }
513                     enableAutoTrimSpecified = true;
514                     break;
515 
516                 case EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE:
517                     if (!clientExtensions.platformANGLED3D ||
518                         !clientExtensions.platformANGLED3D11ON12)
519                     {
520                         return EglBadAttribute()
521                                << "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE extension not active.";
522                     }
523 
524                     switch (value)
525                     {
526                         case EGL_TRUE:
527                         case EGL_FALSE:
528                             break;
529                         default:
530                             return EglBadAttribute() << "Invalid D3D11on12 attribute";
531                     }
532                     enableD3D11on12 = true;
533                     break;
534 
535                 case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
536                     if (!clientExtensions.experimentalPresentPath)
537                     {
538                         return EglBadAttribute()
539                                << "EGL_ANGLE_experimental_present_path extension not active";
540                     }
541 
542                     switch (value)
543                     {
544                         case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
545                         case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
546                             break;
547                         default:
548                             return EglBadAttribute()
549                                    << "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE";
550                     }
551                     presentPathSpecified = true;
552                     break;
553 
554                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
555                     switch (value)
556                     {
557                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
558                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
559                             break;
560 
561                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
562                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
563                             if (!clientExtensions.platformANGLED3D)
564                             {
565                                 return EglBadAttribute()
566                                        << "EGL_ANGLE_platform_angle_d3d is not supported";
567                             }
568                             break;
569 
570                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE:
571                             if (!clientExtensions.platformANGLEDeviceTypeEGLANGLE)
572                             {
573                                 return EglBadAttribute() << "EGL_ANGLE_platform_angle_device_type_"
574                                                             "egl_angle is not supported";
575                             }
576                             break;
577 
578                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
579                             if (!clientExtensions.platformANGLEDeviceTypeSwiftShader)
580                             {
581                                 return EglBadAttribute() << "EGL_ANGLE_platform_angle_device_type_"
582                                                             "swiftshader is not supported";
583                             }
584                             break;
585 
586                         default:
587                             return EglBadAttribute() << "Invalid value for "
588                                                         "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
589                                                         "attrib";
590                     }
591                     deviceType = value;
592                     break;
593 
594                 case EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE:
595                     if (!clientExtensions.platformANGLE)
596                     {
597                         return EglBadAttribute() << "EGL_ANGLE_platform_angle extension not active";
598                     }
599                     if (value != EGL_TRUE && value != EGL_FALSE && value != EGL_DONT_CARE)
600                     {
601                         return EglBadAttribute() << "EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE "
602                                                     "must be EGL_TRUE, EGL_FALSE, or "
603                                                     "EGL_DONT_CARE.";
604                     }
605                     break;
606 
607                 case EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE:
608                     if (value != EGL_DONT_CARE)
609                     {
610                         eglHandle = value;
611                     }
612                     break;
613 
614                 case EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE:
615                     if (!clientExtensions.platformANGLEContextVirtualization)
616                     {
617                         return EglBadAttribute() << "EGL_ANGLE_platform_angle_context_"
618                                                     "virtualization extension not active";
619                     }
620 
621                     switch (value)
622                     {
623                         case EGL_DONT_CARE:
624                         case EGL_FALSE:
625                         case EGL_TRUE:
626                             break;
627 
628                         default:
629                             return EglBadAttribute() << "Invalid value for "
630                                                         "EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_"
631                                                         "ANGLE attrib";
632                     }
633                     break;
634 
635                 case EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE:
636                 case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
637                     luidSpecified = true;
638                     break;
639                 default:
640                     break;
641             }
642         }
643 
644         if (!majorVersion.valid() && minorVersion.valid())
645         {
646             return EglBadAttribute()
647                    << "Must specify major version if you specify a minor version.";
648         }
649 
650         if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE &&
651             platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
652         {
653             return EglBadAttribute() << "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a "
654                                         "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
655         }
656 
657         if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
658         {
659             return EglBadAttribute() << "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE "
660                                         "requires a device type of "
661                                         "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
662         }
663 
664         if (enableD3D11on12)
665         {
666             if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
667             {
668                 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE "
669                                             "requires a platform type of "
670                                             "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
671             }
672 
673             if (deviceType.valid() && deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE &&
674                 deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE)
675             {
676                 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE requires a device "
677                                             "type of EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE "
678                                             "or EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE";
679             }
680         }
681 
682         if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
683         {
684             return EglBadAttribute() << "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a "
685                                         "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
686         }
687 
688         if (luidSpecified)
689         {
690             if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
691             {
692                 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE and "
693                                             "EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE "
694                                             "require a platform type of "
695                                             "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
696             }
697 
698             if (attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0) == 0 &&
699                 attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0) == 0)
700             {
701                 return EglBadAttribute() << "If either EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE "
702                                             "and/or EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE are "
703                                             "specified, at least one must non-zero.";
704             }
705         }
706 
707         if (deviceType.valid())
708         {
709             switch (deviceType.value())
710             {
711                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
712                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
713                     if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
714                         platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
715                     {
716                         return EglBadAttribute()
717                                << "This device type requires a "
718                                   "platform type of EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or "
719                                   "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE.";
720                     }
721                     break;
722 
723                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
724                     if (platformType != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
725                     {
726                         return EglBadAttribute()
727                                << "This device type requires a "
728                                   "platform type of EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.";
729                     }
730                     break;
731 
732                 default:
733                     break;
734             }
735         }
736 
737         if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
738         {
739             if ((majorVersion.valid() && majorVersion.value() != 1) ||
740                 (minorVersion.valid() && minorVersion.value() != 0))
741             {
742                 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently "
743                                             "only supports Vulkan 1.0.";
744             }
745         }
746 
747         if (eglHandle.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
748             platformType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
749         {
750             return EglBadAttribute() << "EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE requires a "
751                                         "device type of EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE.";
752         }
753     }
754     else if (platform == EGL_PLATFORM_DEVICE_EXT)
755     {
756         Device *eglDevice = static_cast<Device *>(native_display);
757         if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
758         {
759             return EglBadAttribute() << "native_display should be a valid EGL device if "
760                                         "platform equals EGL_PLATFORM_DEVICE_EXT";
761         }
762     }
763     else
764     {
765         UNREACHABLE();
766     }
767 
768     if (attribMap.contains(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE))
769     {
770         if (!clientExtensions.featureControlANGLE)
771         {
772             return EglBadAttribute() << "EGL_ANGLE_feature_control is not supported";
773         }
774         else if (attribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0) == 0)
775         {
776             return EglBadAttribute()
777                    << "EGL_FEATURE_OVERRIDES_ENABLED_ANGLE must be a valid pointer";
778         }
779     }
780     if (attribMap.contains(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE))
781     {
782         if (!clientExtensions.featureControlANGLE)
783         {
784             return EglBadAttribute() << "EGL_ANGLE_feature_control is not supported";
785         }
786         else if (attribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0) == 0)
787         {
788             return EglBadAttribute()
789                    << "EGL_FEATURE_OVERRIDES_DISABLED_ANGLE must be a valid pointer";
790         }
791     }
792 
793     return NoError();
794 }
795 
ValidateStream(const Display * display,const Stream * stream)796 Error ValidateStream(const Display *display, const Stream *stream)
797 {
798     ANGLE_TRY(ValidateDisplay(display));
799 
800     const DisplayExtensions &displayExtensions = display->getExtensions();
801     if (!displayExtensions.stream)
802     {
803         return EglBadAccess() << "Stream extension not active";
804     }
805 
806     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
807     {
808         return EglBadStream() << "Invalid stream";
809     }
810 
811     return NoError();
812 }
813 
ValidateLabeledObject(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object,LabeledObject ** outLabeledObject)814 Error ValidateLabeledObject(Thread *thread,
815                             const Display *display,
816                             ObjectType objectType,
817                             EGLObjectKHR object,
818                             LabeledObject **outLabeledObject)
819 {
820     switch (objectType)
821     {
822         case ObjectType::Context:
823         {
824             gl::Context *context = static_cast<gl::Context *>(object);
825             ANGLE_TRY(ValidateContext(display, context));
826             *outLabeledObject = context;
827             break;
828         }
829 
830         case ObjectType::Display:
831         {
832             ANGLE_TRY(ValidateDisplay(display));
833             if (display != object)
834             {
835                 return EglBadParameter() << "when object type is EGL_OBJECT_DISPLAY_KHR, the "
836                                             "object must be the same as the display.";
837             }
838 
839             *outLabeledObject = static_cast<Display *>(object);
840             break;
841         }
842 
843         case ObjectType::Image:
844         {
845             Image *image = static_cast<Image *>(object);
846             ANGLE_TRY(ValidateImage(display, image));
847             *outLabeledObject = image;
848             break;
849         }
850 
851         case ObjectType::Stream:
852         {
853             Stream *stream = static_cast<Stream *>(object);
854             ANGLE_TRY(ValidateStream(display, stream));
855             *outLabeledObject = stream;
856             break;
857         }
858 
859         case ObjectType::Surface:
860         {
861             Surface *surface = static_cast<Surface *>(object);
862             ANGLE_TRY(ValidateSurface(display, surface));
863             *outLabeledObject = surface;
864             break;
865         }
866 
867         case ObjectType::Sync:
868         {
869             Sync *sync = static_cast<Sync *>(object);
870             ANGLE_TRY(ValidateSync(display, sync));
871             *outLabeledObject = sync;
872             break;
873         }
874 
875         case ObjectType::Thread:
876         {
877             *outLabeledObject = thread;
878             break;
879         }
880 
881         default:
882             return EglBadParameter() << "unknown object type.";
883     }
884 
885     return NoError();
886 }
887 
888 // This is a common sub-check of Display status that's shared by multiple functions
ValidateDisplayPointer(const Display * display)889 Error ValidateDisplayPointer(const Display *display)
890 {
891     if (display == EGL_NO_DISPLAY)
892     {
893         return EglBadDisplay() << "display is EGL_NO_DISPLAY.";
894     }
895 
896     if (!Display::isValidDisplay(display))
897     {
898         return EglBadDisplay() << "display is not a valid display.";
899     }
900 
901     return NoError();
902 }
903 
ValidCompositorTimingName(CompositorTiming name)904 bool ValidCompositorTimingName(CompositorTiming name)
905 {
906     switch (name)
907     {
908         case CompositorTiming::CompositeDeadline:
909         case CompositorTiming::CompositInterval:
910         case CompositorTiming::CompositToPresentLatency:
911             return true;
912 
913         default:
914             return false;
915     }
916 }
917 
ValidTimestampType(Timestamp timestamp)918 bool ValidTimestampType(Timestamp timestamp)
919 {
920     switch (timestamp)
921     {
922         case Timestamp::RequestedPresentTime:
923         case Timestamp::RenderingCompleteTime:
924         case Timestamp::CompositionLatchTime:
925         case Timestamp::FirstCompositionStartTime:
926         case Timestamp::LastCompositionStartTime:
927         case Timestamp::FirstCompositionGPUFinishedTime:
928         case Timestamp::DisplayPresentTime:
929         case Timestamp::DequeueReadyTime:
930         case Timestamp::ReadsDoneTime:
931             return true;
932 
933         default:
934             return false;
935     }
936 }
937 
938 }  // anonymous namespace
939 
ValidateDisplay(const Display * display)940 Error ValidateDisplay(const Display *display)
941 {
942     ANGLE_TRY(ValidateDisplayPointer(display));
943 
944     if (!display->isInitialized())
945     {
946         return EglNotInitialized() << "display is not initialized.";
947     }
948 
949     if (display->isDeviceLost())
950     {
951         return EglContextLost() << "display had a context loss";
952     }
953 
954     return NoError();
955 }
956 
ValidateSurface(const Display * display,const Surface * surface)957 Error ValidateSurface(const Display *display, const Surface *surface)
958 {
959     ANGLE_TRY(ValidateDisplay(display));
960 
961     if (!display->isValidSurface(surface))
962     {
963         return EglBadSurface();
964     }
965 
966     return NoError();
967 }
968 
ValidateConfig(const Display * display,const Config * config)969 Error ValidateConfig(const Display *display, const Config *config)
970 {
971     ANGLE_TRY(ValidateDisplay(display));
972 
973     if (!display->isValidConfig(config))
974     {
975         return EglBadConfig();
976     }
977 
978     return NoError();
979 }
980 
ValidateContext(const Display * display,const gl::Context * context)981 Error ValidateContext(const Display *display, const gl::Context *context)
982 {
983     ANGLE_TRY(ValidateDisplay(display));
984 
985     if (!display->isValidContext(context))
986     {
987         return EglBadContext();
988     }
989 
990     return NoError();
991 }
992 
ValidateImage(const Display * display,const Image * image)993 Error ValidateImage(const Display *display, const Image *image)
994 {
995     ANGLE_TRY(ValidateDisplay(display));
996 
997     if (!display->isValidImage(image))
998     {
999         return EglBadParameter() << "image is not valid.";
1000     }
1001 
1002     return NoError();
1003 }
1004 
ValidateDevice(const Device * device)1005 Error ValidateDevice(const Device *device)
1006 {
1007     if (device == EGL_NO_DEVICE_EXT)
1008     {
1009         return EglBadAccess() << "device is EGL_NO_DEVICE.";
1010     }
1011 
1012     if (!Device::IsValidDevice(device))
1013     {
1014         return EglBadAccess() << "device is not valid.";
1015     }
1016 
1017     return NoError();
1018 }
1019 
ValidateSync(const Display * display,const Sync * sync)1020 Error ValidateSync(const Display *display, const Sync *sync)
1021 {
1022     ANGLE_TRY(ValidateDisplay(display));
1023 
1024     if (!display->isValidSync(sync))
1025     {
1026         return EglBadParameter() << "sync object is not valid.";
1027     }
1028 
1029     return NoError();
1030 }
1031 
GetThreadIfValid(const Thread * thread)1032 const Thread *GetThreadIfValid(const Thread *thread)
1033 {
1034     // Threads should always be valid
1035     return thread;
1036 }
1037 
GetDisplayIfValid(const Display * display)1038 const Display *GetDisplayIfValid(const Display *display)
1039 {
1040     if (ValidateDisplay(display).isError())
1041     {
1042         return nullptr;
1043     }
1044 
1045     return display;
1046 }
1047 
GetSurfaceIfValid(const Display * display,const Surface * surface)1048 const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface)
1049 {
1050     if (ValidateSurface(display, surface).isError())
1051     {
1052         return nullptr;
1053     }
1054 
1055     return surface;
1056 }
1057 
GetImageIfValid(const Display * display,const Image * image)1058 const Image *GetImageIfValid(const Display *display, const Image *image)
1059 {
1060     if (ValidateImage(display, image).isError())
1061     {
1062         return nullptr;
1063     }
1064 
1065     return image;
1066 }
1067 
GetStreamIfValid(const Display * display,const Stream * stream)1068 const Stream *GetStreamIfValid(const Display *display, const Stream *stream)
1069 {
1070     if (ValidateStream(display, stream).isError())
1071     {
1072         return nullptr;
1073     }
1074 
1075     return stream;
1076 }
1077 
GetContextIfValid(const Display * display,const gl::Context * context)1078 const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context)
1079 {
1080     if (ValidateContext(display, context).isError())
1081     {
1082         return nullptr;
1083     }
1084 
1085     return context;
1086 }
1087 
GetDeviceIfValid(const Device * device)1088 const Device *GetDeviceIfValid(const Device *device)
1089 {
1090     if (ValidateDevice(device).isError())
1091     {
1092         return nullptr;
1093     }
1094 
1095     return device;
1096 }
1097 
GetSyncIfValid(const Display * display,const Sync * sync)1098 const Sync *GetSyncIfValid(const Display *display, const Sync *sync)
1099 {
1100     if (ValidateSync(display, sync).isError())
1101     {
1102         return nullptr;
1103     }
1104 
1105     return sync;
1106 }
1107 
GetLabeledObjectIfValid(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object)1108 LabeledObject *GetLabeledObjectIfValid(Thread *thread,
1109                                        const Display *display,
1110                                        ObjectType objectType,
1111                                        EGLObjectKHR object)
1112 {
1113     LabeledObject *labeledObject = nullptr;
1114     if (ValidateLabeledObject(thread, display, objectType, object, &labeledObject).isError())
1115     {
1116         return nullptr;
1117     }
1118 
1119     return labeledObject;
1120 }
1121 
ValidateInitialize(const Display * display)1122 Error ValidateInitialize(const Display *display)
1123 {
1124     return ValidateDisplayPointer(display);
1125 }
1126 
ValidateTerminate(const Display * display)1127 Error ValidateTerminate(const Display *display)
1128 {
1129     return ValidateDisplayPointer(display);
1130 }
1131 
ValidateCreateContext(Display * display,Config * configuration,gl::Context * shareContext,const AttributeMap & attributes)1132 Error ValidateCreateContext(Display *display,
1133                             Config *configuration,
1134                             gl::Context *shareContext,
1135                             const AttributeMap &attributes)
1136 {
1137     if (configuration)
1138     {
1139         ANGLE_TRY(ValidateConfig(display, configuration));
1140     }
1141     else
1142     {
1143         ANGLE_TRY(ValidateDisplay(display));
1144         const DisplayExtensions &displayExtensions = display->getExtensions();
1145         if (!displayExtensions.noConfigContext)
1146         {
1147             return EglBadConfig();
1148         }
1149     }
1150 
1151     // Get the requested client version (default is 1) and check it is 2 or 3.
1152     EGLAttrib clientMajorVersion = 1;
1153     EGLAttrib clientMinorVersion = 0;
1154     EGLAttrib contextFlags       = 0;
1155     bool resetNotification       = false;
1156     for (AttributeMap::const_iterator attributeIter = attributes.begin();
1157          attributeIter != attributes.end(); attributeIter++)
1158     {
1159         EGLAttrib attribute = attributeIter->first;
1160         EGLAttrib value     = attributeIter->second;
1161 
1162         switch (attribute)
1163         {
1164             case EGL_CONTEXT_CLIENT_VERSION:
1165                 clientMajorVersion = value;
1166                 break;
1167 
1168             case EGL_CONTEXT_MINOR_VERSION:
1169                 clientMinorVersion = value;
1170                 break;
1171 
1172             case EGL_CONTEXT_FLAGS_KHR:
1173                 contextFlags = value;
1174                 break;
1175 
1176             case EGL_CONTEXT_OPENGL_DEBUG:
1177                 break;
1178 
1179             case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
1180                 // Only valid for OpenGL (non-ES) contexts
1181                 return EglBadAttribute();
1182 
1183             case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
1184                 if (!display->getExtensions().createContextRobustness)
1185                 {
1186                     return EglBadAttribute();
1187                 }
1188                 if (value != EGL_TRUE && value != EGL_FALSE)
1189                 {
1190                     return EglBadAttribute();
1191                 }
1192                 break;
1193 
1194             case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
1195                 return EglBadAttribute()
1196                        << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR is not"
1197                        << " valid for GLES with EGL 1.4 and KHR_create_context. Use"
1198                        << " EXT_create_context_robustness.";
1199             case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
1200                 if (!display->getExtensions().createContextRobustness)
1201                 {
1202                     return EglBadAttribute();
1203                 }
1204                 if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT)
1205                 {
1206                     resetNotification = true;
1207                 }
1208                 else if (value != EGL_NO_RESET_NOTIFICATION_EXT)
1209                 {
1210                     return EglBadAttribute();
1211                 }
1212                 break;
1213 
1214             case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
1215                 if (!display->getExtensions().createContextNoError)
1216                 {
1217                     return EglBadAttribute() << "Invalid Context attribute.";
1218                 }
1219                 if (value != EGL_TRUE && value != EGL_FALSE)
1220                 {
1221                     return EglBadAttribute() << "Attribute must be EGL_TRUE or EGL_FALSE.";
1222                 }
1223                 break;
1224 
1225             case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
1226                 if (!display->getExtensions().createContextWebGLCompatibility)
1227                 {
1228                     return EglBadAttribute() << "Attribute "
1229                                                 "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
1230                                                 "EGL_ANGLE_create_context_webgl_compatibility.";
1231                 }
1232                 if (value != EGL_TRUE && value != EGL_FALSE)
1233                 {
1234                     return EglBadAttribute() << "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be "
1235                                                 "EGL_TRUE or EGL_FALSE.";
1236                 }
1237                 break;
1238 
1239             case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
1240                 if (!display->getExtensions().createContextBindGeneratesResource)
1241                 {
1242                     return EglBadAttribute()
1243                            << "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
1244                               "EGL_CHROMIUM_create_context_bind_generates_resource.";
1245                 }
1246                 if (value != EGL_TRUE && value != EGL_FALSE)
1247                 {
1248                     return EglBadAttribute() << "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM "
1249                                                 "must be EGL_TRUE or EGL_FALSE.";
1250                 }
1251                 break;
1252 
1253             case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
1254                 if (!display->getExtensions().displayTextureShareGroup)
1255                 {
1256                     return EglBadAttribute() << "Attribute "
1257                                                 "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
1258                                                 "EGL_ANGLE_display_texture_share_group.";
1259                 }
1260                 if (value != EGL_TRUE && value != EGL_FALSE)
1261                 {
1262                     return EglBadAttribute() << "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be "
1263                                                 "EGL_TRUE or EGL_FALSE.";
1264                 }
1265                 if (shareContext &&
1266                     (shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE)))
1267                 {
1268                     return EglBadAttribute() << "All contexts within a share group must be "
1269                                                 "created with the same value of "
1270                                                 "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.";
1271                 }
1272                 break;
1273 
1274             case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
1275                 if (!display->getExtensions().createContextClientArrays)
1276                 {
1277                     return EglBadAttribute()
1278                            << "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
1279                               "EGL_ANGLE_create_context_client_arrays.";
1280                 }
1281                 if (value != EGL_TRUE && value != EGL_FALSE)
1282                 {
1283                     return EglBadAttribute() << "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must "
1284                                                 "be EGL_TRUE or EGL_FALSE.";
1285                 }
1286                 break;
1287 
1288             case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
1289                 if (!display->getExtensions().programCacheControl)
1290                 {
1291                     return EglBadAttribute()
1292                            << "Attribute EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE "
1293                               "requires EGL_ANGLE_program_cache_control.";
1294                 }
1295                 if (value != EGL_TRUE && value != EGL_FALSE)
1296                 {
1297                     return EglBadAttribute()
1298                            << "EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE must "
1299                               "be EGL_TRUE or EGL_FALSE.";
1300                 }
1301                 break;
1302 
1303             case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1304                 if (!display->getExtensions().robustResourceInitialization)
1305                 {
1306                     return EglBadAttribute()
1307                            << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1308                               "requires EGL_ANGLE_robust_resource_initialization.";
1309                 }
1310                 if (value != EGL_TRUE && value != EGL_FALSE)
1311                 {
1312                     return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1313                                                 "either EGL_TRUE or EGL_FALSE.";
1314                 }
1315                 break;
1316 
1317             case EGL_EXTENSIONS_ENABLED_ANGLE:
1318                 if (!display->getExtensions().createContextExtensionsEnabled)
1319                 {
1320                     return EglBadAttribute()
1321                            << "Attribute EGL_EXTENSIONS_ENABLED_ANGLE "
1322                               "requires EGL_ANGLE_create_context_extensions_enabled.";
1323                 }
1324                 if (value != EGL_TRUE && value != EGL_FALSE)
1325                 {
1326                     return EglBadAttribute() << "EGL_EXTENSIONS_ENABLED_ANGLE must be "
1327                                                 "either EGL_TRUE or EGL_FALSE.";
1328                 }
1329                 break;
1330 
1331             case EGL_POWER_PREFERENCE_ANGLE:
1332                 if (!display->getExtensions().powerPreference)
1333                 {
1334                     return EglBadAttribute() << "Attribute EGL_POWER_PREFERENCE_ANGLE "
1335                                                 "requires EGL_ANGLE_power_preference.";
1336                 }
1337                 if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
1338                 {
1339                     return EglBadAttribute()
1340                            << "EGL_POWER_PREFERENCE_ANGLE must be "
1341                               "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.";
1342                 }
1343                 break;
1344 
1345             case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
1346                 if (!display->getExtensions().createContextBackwardsCompatible)
1347                 {
1348                     return EglBadAttribute()
1349                            << "Attribute EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE "
1350                               "requires EGL_ANGLE_create_context_backwards_compatible.";
1351                 }
1352                 if (value != EGL_TRUE && value != EGL_FALSE)
1353                 {
1354                     return EglBadAttribute()
1355                            << "EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE must be "
1356                               "either EGL_TRUE or EGL_FALSE.";
1357                 }
1358                 break;
1359 
1360             case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
1361                 if (!display->getExtensions().contextPriority)
1362                 {
1363                     return EglBadAttribute() << "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
1364                                                 "extension EGL_IMG_context_priority.";
1365                 }
1366                 switch (value)
1367                 {
1368                     case EGL_CONTEXT_PRIORITY_LOW_IMG:
1369                     case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1370                     case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1371                         break;
1372                     default:
1373                         return EglBadAttribute() << "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG "
1374                                                     "must be one of: EGL_CONTEXT_PRIORITY_LOW_IMG, "
1375                                                     "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, or "
1376                                                     "EGL_CONTEXT_PRIORITY_HIGH_IMG.";
1377                 }
1378                 break;
1379 
1380             default:
1381                 return EglBadAttribute() << "Unknown attribute.";
1382         }
1383     }
1384 
1385     switch (clientMajorVersion)
1386     {
1387         case 1:
1388             if (clientMinorVersion != 0 && clientMinorVersion != 1)
1389             {
1390                 return EglBadAttribute();
1391             }
1392             if (configuration == EGL_NO_CONFIG_KHR)
1393             {
1394                 return EglBadMatch();
1395             }
1396             if ((configuration != EGL_NO_CONFIG_KHR) &&
1397                 !(configuration->renderableType & EGL_OPENGL_ES_BIT))
1398             {
1399                 return EglBadMatch();
1400             }
1401             break;
1402 
1403         case 2:
1404             if (clientMinorVersion != 0)
1405             {
1406                 return EglBadAttribute();
1407             }
1408             if ((configuration != EGL_NO_CONFIG_KHR) &&
1409                 !(configuration->renderableType & EGL_OPENGL_ES2_BIT))
1410             {
1411                 return EglBadMatch();
1412             }
1413             break;
1414         case 3:
1415             if (clientMinorVersion != 0 && clientMinorVersion != 1)
1416             {
1417                 return EglBadAttribute();
1418             }
1419             if ((configuration != EGL_NO_CONFIG_KHR) &&
1420                 !(configuration->renderableType & EGL_OPENGL_ES3_BIT))
1421             {
1422                 return EglBadMatch();
1423             }
1424             if (display->getMaxSupportedESVersion() <
1425                 gl::Version(static_cast<GLuint>(clientMajorVersion),
1426                             static_cast<GLuint>(clientMinorVersion)))
1427             {
1428                 return EglBadAttribute() << "Requested GLES version is not supported.";
1429             }
1430             break;
1431         default:
1432             return EglBadAttribute();
1433             break;
1434     }
1435 
1436     // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
1437     const EGLint validContextFlags =
1438         (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
1439     if ((contextFlags & ~validContextFlags) != 0)
1440     {
1441         return EglBadAttribute();
1442     }
1443 
1444     if (shareContext)
1445     {
1446         // Shared context is invalid or is owned by another display
1447         if (!display->isValidContext(shareContext))
1448         {
1449             return EglBadMatch();
1450         }
1451 
1452         if (shareContext->isResetNotificationEnabled() != resetNotification)
1453         {
1454             return EglBadMatch();
1455         }
1456     }
1457 
1458     return NoError();
1459 }
1460 
ValidateCreateWindowSurface(Display * display,Config * config,EGLNativeWindowType window,const AttributeMap & attributes)1461 Error ValidateCreateWindowSurface(Display *display,
1462                                   Config *config,
1463                                   EGLNativeWindowType window,
1464                                   const AttributeMap &attributes)
1465 {
1466     ANGLE_TRY(ValidateConfig(display, config));
1467 
1468     if (!display->isValidNativeWindow(window))
1469     {
1470         return EglBadNativeWindow();
1471     }
1472 
1473     const DisplayExtensions &displayExtensions = display->getExtensions();
1474 
1475     for (AttributeMap::const_iterator attributeIter = attributes.begin();
1476          attributeIter != attributes.end(); attributeIter++)
1477     {
1478         EGLAttrib attribute = attributeIter->first;
1479         EGLAttrib value     = attributeIter->second;
1480 
1481         switch (attribute)
1482         {
1483             case EGL_RENDER_BUFFER:
1484                 switch (value)
1485                 {
1486                     case EGL_BACK_BUFFER:
1487                         break;
1488                     case EGL_SINGLE_BUFFER:
1489                         return EglBadMatch();  // Rendering directly to front buffer not supported
1490                     default:
1491                         return EglBadAttribute();
1492                 }
1493                 break;
1494 
1495             case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
1496                 if (!displayExtensions.postSubBuffer)
1497                 {
1498                     return EglBadAttribute();
1499                 }
1500                 break;
1501 
1502             case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
1503                 if (!displayExtensions.flexibleSurfaceCompatibility)
1504                 {
1505                     return EglBadAttribute();
1506                 }
1507                 break;
1508 
1509             case EGL_WIDTH:
1510             case EGL_HEIGHT:
1511                 if (!displayExtensions.windowFixedSize)
1512                 {
1513                     return EglBadAttribute();
1514                 }
1515                 if (value < 0)
1516                 {
1517                     return EglBadParameter();
1518                 }
1519                 break;
1520 
1521             case EGL_FIXED_SIZE_ANGLE:
1522                 if (!displayExtensions.windowFixedSize)
1523                 {
1524                     return EglBadAttribute();
1525                 }
1526                 break;
1527 
1528             case EGL_SURFACE_ORIENTATION_ANGLE:
1529                 if (!displayExtensions.surfaceOrientation)
1530                 {
1531                     return EglBadAttribute() << "EGL_ANGLE_surface_orientation is not enabled.";
1532                 }
1533                 break;
1534 
1535             case EGL_VG_COLORSPACE:
1536                 return EglBadMatch();
1537 
1538             case EGL_GL_COLORSPACE:
1539                 ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
1540                 break;
1541 
1542             case EGL_VG_ALPHA_FORMAT:
1543                 return EglBadMatch();
1544 
1545             case EGL_DIRECT_COMPOSITION_ANGLE:
1546                 if (!displayExtensions.directComposition)
1547                 {
1548                     return EglBadAttribute();
1549                 }
1550                 break;
1551 
1552             case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1553                 if (!display->getExtensions().robustResourceInitialization)
1554                 {
1555                     return EglBadAttribute()
1556                            << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1557                               "requires EGL_ANGLE_robust_resource_initialization.";
1558                 }
1559                 if (value != EGL_TRUE && value != EGL_FALSE)
1560                 {
1561                     return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1562                                                 "either EGL_TRUE or EGL_FALSE.";
1563                 }
1564                 break;
1565 
1566             case EGL_GGP_STREAM_DESCRIPTOR_ANGLE:
1567                 if (!display->getExtensions().ggpStreamDescriptor)
1568                 {
1569                     return EglBadAttribute() << "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires "
1570                                                 "EGL_ANGLE_ggp_stream_descriptor.";
1571                 }
1572                 break;
1573 
1574             default:
1575                 return EglBadAttribute();
1576         }
1577     }
1578 
1579     if (Display::hasExistingWindowSurface(window))
1580     {
1581         return EglBadAlloc();
1582     }
1583 
1584     return NoError();
1585 }
1586 
ValidateCreatePbufferSurface(Display * display,Config * config,const AttributeMap & attributes)1587 Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap &attributes)
1588 {
1589     ANGLE_TRY(ValidateConfig(display, config));
1590 
1591     const DisplayExtensions &displayExtensions = display->getExtensions();
1592 
1593     for (AttributeMap::const_iterator attributeIter = attributes.begin();
1594          attributeIter != attributes.end(); attributeIter++)
1595     {
1596         EGLAttrib attribute = attributeIter->first;
1597         EGLAttrib value     = attributeIter->second;
1598 
1599         switch (attribute)
1600         {
1601             case EGL_WIDTH:
1602             case EGL_HEIGHT:
1603                 if (value < 0)
1604                 {
1605                     return EglBadParameter();
1606                 }
1607                 break;
1608 
1609             case EGL_LARGEST_PBUFFER:
1610                 break;
1611 
1612             case EGL_TEXTURE_FORMAT:
1613                 switch (value)
1614                 {
1615                     case EGL_NO_TEXTURE:
1616                     case EGL_TEXTURE_RGB:
1617                     case EGL_TEXTURE_RGBA:
1618                         break;
1619                     default:
1620                         return EglBadAttribute();
1621                 }
1622                 break;
1623 
1624             case EGL_TEXTURE_TARGET:
1625                 switch (value)
1626                 {
1627                     case EGL_NO_TEXTURE:
1628                     case EGL_TEXTURE_2D:
1629                         break;
1630                     default:
1631                         return EglBadAttribute();
1632                 }
1633                 break;
1634 
1635             case EGL_MIPMAP_TEXTURE:
1636                 break;
1637 
1638             case EGL_VG_COLORSPACE:
1639                 break;
1640 
1641             case EGL_GL_COLORSPACE:
1642                 ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
1643                 break;
1644 
1645             case EGL_VG_ALPHA_FORMAT:
1646                 break;
1647 
1648             case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
1649                 if (!displayExtensions.flexibleSurfaceCompatibility)
1650                 {
1651                     return EglBadAttribute()
1652                            << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
1653                               "without EGL_ANGLE_flexible_surface_compatibility support.";
1654                 }
1655                 break;
1656 
1657             case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1658                 if (!display->getExtensions().robustResourceInitialization)
1659                 {
1660                     return EglBadAttribute()
1661                            << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1662                               "requires EGL_ANGLE_robust_resource_initialization.";
1663                 }
1664                 if (value != EGL_TRUE && value != EGL_FALSE)
1665                 {
1666                     return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1667                                                 "either EGL_TRUE or EGL_FALSE.";
1668                 }
1669                 break;
1670 
1671             default:
1672                 return EglBadAttribute();
1673         }
1674     }
1675 
1676     if (!(config->surfaceType & EGL_PBUFFER_BIT))
1677     {
1678         return EglBadMatch();
1679     }
1680 
1681     const Caps &caps = display->getCaps();
1682 
1683     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
1684     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
1685 
1686     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
1687         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
1688     {
1689         return EglBadMatch();
1690     }
1691 
1692     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
1693         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
1694     {
1695         return EglBadAttribute();
1696     }
1697 
1698     EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
1699     EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
1700     if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
1701         (!gl::isPow2(width) || !gl::isPow2(height)))
1702     {
1703         return EglBadMatch();
1704     }
1705 
1706     return NoError();
1707 }
1708 
ValidateCreatePbufferFromClientBuffer(Display * display,EGLenum buftype,EGLClientBuffer buffer,Config * config,const AttributeMap & attributes)1709 Error ValidateCreatePbufferFromClientBuffer(Display *display,
1710                                             EGLenum buftype,
1711                                             EGLClientBuffer buffer,
1712                                             Config *config,
1713                                             const AttributeMap &attributes)
1714 {
1715     ANGLE_TRY(ValidateConfig(display, config));
1716 
1717     const DisplayExtensions &displayExtensions = display->getExtensions();
1718 
1719     switch (buftype)
1720     {
1721         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
1722             if (!displayExtensions.d3dShareHandleClientBuffer)
1723             {
1724                 return EglBadParameter();
1725             }
1726             if (buffer == nullptr)
1727             {
1728                 return EglBadParameter();
1729             }
1730             break;
1731 
1732         case EGL_D3D_TEXTURE_ANGLE:
1733             if (!displayExtensions.d3dTextureClientBuffer)
1734             {
1735                 return EglBadParameter();
1736             }
1737             if (buffer == nullptr)
1738             {
1739                 return EglBadParameter();
1740             }
1741             break;
1742 
1743         case EGL_IOSURFACE_ANGLE:
1744             if (!displayExtensions.iosurfaceClientBuffer)
1745             {
1746                 return EglBadParameter() << "<buftype> EGL_IOSURFACE_ANGLE requires the "
1747                                             "EGL_ANGLE_iosurface_client_buffer extension.";
1748             }
1749             if (buffer == nullptr)
1750             {
1751                 return EglBadParameter() << "<buffer> must be non null";
1752             }
1753             break;
1754 
1755         default:
1756             return EglBadParameter();
1757     }
1758 
1759     for (AttributeMap::const_iterator attributeIter = attributes.begin();
1760          attributeIter != attributes.end(); attributeIter++)
1761     {
1762         EGLAttrib attribute = attributeIter->first;
1763         EGLAttrib value     = attributeIter->second;
1764 
1765         switch (attribute)
1766         {
1767             case EGL_WIDTH:
1768             case EGL_HEIGHT:
1769                 if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
1770                     buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE)
1771                 {
1772                     return EglBadParameter()
1773                            << "Width and Height are not supported for thie <buftype>";
1774                 }
1775                 if (value < 0)
1776                 {
1777                     return EglBadParameter() << "Width and Height must be positive";
1778                 }
1779                 break;
1780 
1781             case EGL_TEXTURE_FORMAT:
1782                 switch (value)
1783                 {
1784                     case EGL_NO_TEXTURE:
1785                     case EGL_TEXTURE_RGB:
1786                     case EGL_TEXTURE_RGBA:
1787                         break;
1788                     default:
1789                         return EglBadAttribute() << "Invalid value for EGL_TEXTURE_FORMAT";
1790                 }
1791                 break;
1792 
1793             case EGL_TEXTURE_TARGET:
1794                 switch (value)
1795                 {
1796                     case EGL_NO_TEXTURE:
1797                     case EGL_TEXTURE_2D:
1798                         break;
1799                     case EGL_TEXTURE_RECTANGLE_ANGLE:
1800                         if (buftype != EGL_IOSURFACE_ANGLE)
1801                         {
1802                             return EglBadParameter()
1803                                    << "<buftype> doesn't support rectangle texture targets";
1804                         }
1805                         break;
1806 
1807                     default:
1808                         return EglBadAttribute() << "Invalid value for EGL_TEXTURE_TARGET";
1809                 }
1810                 break;
1811 
1812             case EGL_MIPMAP_TEXTURE:
1813                 break;
1814 
1815             case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
1816                 if (!displayExtensions.flexibleSurfaceCompatibility)
1817                 {
1818                     return EglBadAttribute()
1819                            << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
1820                               "without EGL_ANGLE_flexible_surface_compatibility support.";
1821                 }
1822                 break;
1823 
1824             case EGL_IOSURFACE_PLANE_ANGLE:
1825                 if (buftype != EGL_IOSURFACE_ANGLE)
1826                 {
1827                     return EglBadAttribute() << "<buftype> doesn't support iosurface plane";
1828                 }
1829                 break;
1830 
1831             case EGL_TEXTURE_TYPE_ANGLE:
1832                 if (buftype != EGL_IOSURFACE_ANGLE)
1833                 {
1834                     return EglBadAttribute() << "<buftype> doesn't support texture type";
1835                 }
1836                 break;
1837 
1838             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
1839                 if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
1840                 {
1841                     return EglBadAttribute() << "<buftype> doesn't support texture internal format";
1842                 }
1843                 break;
1844 
1845             case EGL_GL_COLORSPACE:
1846                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
1847                 {
1848                     return EglBadAttribute() << "<buftype> doesn't support setting GL colorspace";
1849                 }
1850                 break;
1851 
1852             case EGL_IOSURFACE_USAGE_HINT_ANGLE:
1853                 if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
1854                 {
1855                     return EglBadAttribute()
1856                            << "IOSurface usage hint must only contain READ or WRITE";
1857                 }
1858                 break;
1859 
1860             case EGL_TEXTURE_OFFSET_X_ANGLE:
1861             case EGL_TEXTURE_OFFSET_Y_ANGLE:
1862                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
1863                 {
1864                     return EglBadAttribute() << "<buftype> doesn't support setting texture offset";
1865                 }
1866                 if (value < 0)
1867                 {
1868                     return EglBadAttribute() << "Texture offset cannot be negative";
1869                 }
1870                 break;
1871 
1872             default:
1873                 return EglBadAttribute();
1874         }
1875     }
1876 
1877     EGLAttrib colorspace = attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
1878     if (colorspace != EGL_GL_COLORSPACE_LINEAR && colorspace != EGL_GL_COLORSPACE_SRGB)
1879     {
1880         return EglBadAttribute() << "invalid GL colorspace";
1881     }
1882 
1883     if (!(config->surfaceType & EGL_PBUFFER_BIT))
1884     {
1885         return EglBadMatch();
1886     }
1887 
1888     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
1889     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
1890     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
1891         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
1892     {
1893         return EglBadMatch();
1894     }
1895     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
1896         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
1897     {
1898         // TODO(cwallez@chromium.org): For IOSurface pbuffers we require that EGL_TEXTURE_RGBA is
1899         // set so that eglBindTexImage works. Normally this is only allowed if the config exposes
1900         // the bindToTextureRGB/RGBA flag. This issue is that enabling this flags means that
1901         // eglBindTexImage should also work for regular pbuffers which isn't implemented on macOS.
1902         // Instead of adding the flag we special case the check here to be ignored for IOSurfaces.
1903         // The TODO is to find a proper solution for this, maybe by implementing eglBindTexImage on
1904         // OSX?
1905         if (buftype != EGL_IOSURFACE_ANGLE)
1906         {
1907             return EglBadAttribute();
1908         }
1909     }
1910 
1911     if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
1912     {
1913         EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
1914         EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
1915 
1916         if (width == 0 || height == 0)
1917         {
1918             return EglBadAttribute();
1919         }
1920 
1921         const Caps &caps = display->getCaps();
1922         if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
1923             (!gl::isPow2(width) || !gl::isPow2(height)))
1924         {
1925             return EglBadMatch();
1926         }
1927     }
1928 
1929     if (buftype == EGL_IOSURFACE_ANGLE)
1930     {
1931         if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
1932         {
1933             return EglBadAttribute()
1934                    << "EGL_IOSURFACE requires the texture target to match the config";
1935         }
1936         if (textureFormat != EGL_TEXTURE_RGBA)
1937         {
1938             return EglBadAttribute() << "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format";
1939         }
1940 
1941         if (!attributes.contains(EGL_WIDTH) || !attributes.contains(EGL_HEIGHT) ||
1942             !attributes.contains(EGL_TEXTURE_FORMAT) ||
1943             !attributes.contains(EGL_TEXTURE_TYPE_ANGLE) ||
1944             !attributes.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE) ||
1945             !attributes.contains(EGL_IOSURFACE_PLANE_ANGLE))
1946         {
1947             return EglBadParameter() << "Missing required attribute for EGL_IOSURFACE";
1948         }
1949     }
1950 
1951     ANGLE_TRY(display->validateClientBuffer(config, buftype, buffer, attributes));
1952 
1953     return NoError();
1954 }
1955 
ValidateMakeCurrent(Display * display,Surface * draw,Surface * read,gl::Context * context)1956 Error ValidateMakeCurrent(Display *display, Surface *draw, Surface *read, gl::Context *context)
1957 {
1958     if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
1959     {
1960         return EglBadMatch() << "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE";
1961     }
1962 
1963     // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
1964     // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
1965     if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
1966     {
1967         if (display->getExtensions().surfacelessContext)
1968         {
1969             if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
1970             {
1971                 return EglBadMatch() << "If ctx is not EGL_NOT_CONTEXT, draw or read must "
1972                                         "both be EGL_NO_SURFACE, or both not";
1973             }
1974         }
1975         else
1976         {
1977             return EglBadMatch()
1978                    << "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE";
1979         }
1980     }
1981 
1982     // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
1983     // EGL_BAD_MATCH error is generated.
1984     if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
1985     {
1986         return EglBadMatch()
1987                << "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE";
1988     }
1989 
1990     if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
1991     {
1992         return EglBadDisplay() << "'dpy' not a valid EGLDisplay handle";
1993     }
1994 
1995     // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
1996     if (!display->isInitialized() &&
1997         (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
1998     {
1999         return EglNotInitialized() << "'dpy' not initialized";
2000     }
2001 
2002     if (context != EGL_NO_CONTEXT)
2003     {
2004         ANGLE_TRY(ValidateContext(display, context));
2005     }
2006 
2007     if (display->isInitialized() && display->isDeviceLost())
2008     {
2009         return EglContextLost();
2010     }
2011 
2012     if (draw != EGL_NO_SURFACE)
2013     {
2014         ANGLE_TRY(ValidateSurface(display, draw));
2015     }
2016 
2017     if (read != EGL_NO_SURFACE)
2018     {
2019         ANGLE_TRY(ValidateSurface(display, read));
2020         ANGLE_TRY(ValidateCompatibleSurface(display, context, read));
2021     }
2022 
2023     if (draw != read)
2024     {
2025         if (draw)
2026         {
2027             ANGLE_TRY(ValidateCompatibleSurface(display, context, draw));
2028         }
2029         if (read)
2030         {
2031             ANGLE_TRY(ValidateCompatibleSurface(display, context, read));
2032         }
2033     }
2034     return NoError();
2035 }
2036 
ValidateCompatibleSurface(const Display * display,gl::Context * context,const Surface * surface)2037 Error ValidateCompatibleSurface(const Display *display,
2038                                 gl::Context *context,
2039                                 const Surface *surface)
2040 {
2041     const Config *contextConfig = context->getConfig();
2042     const Config *surfaceConfig = surface->getConfig();
2043 
2044     // Surface compatible with client API - only OPENGL_ES supported
2045     switch (context->getClientMajorVersion())
2046     {
2047         case 1:
2048             if (!(surfaceConfig->renderableType & EGL_OPENGL_ES_BIT))
2049             {
2050                 return EglBadMatch() << "Surface not compatible with OpenGL ES 1.x.";
2051             }
2052             break;
2053         case 2:
2054             if (!(surfaceConfig->renderableType & EGL_OPENGL_ES2_BIT))
2055             {
2056                 return EglBadMatch() << "Surface not compatible with OpenGL ES 2.x.";
2057             }
2058             break;
2059         case 3:
2060             if (!(surfaceConfig->renderableType & (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT)))
2061             {
2062                 return EglBadMatch() << "Surface not compatible with OpenGL ES 3.x.";
2063             }
2064             break;
2065         default:
2066             return EglBadMatch() << "Surface not compatible with Context API.";
2067     }
2068 
2069     // EGL KHR no config context
2070     if (context->getConfig() == EGL_NO_CONFIG_KHR)
2071     {
2072         const DisplayExtensions &displayExtensions = display->getExtensions();
2073         if (displayExtensions.noConfigContext)
2074         {
2075             return NoError();
2076         }
2077         return EglBadMatch() << "Context with no config is not supported.";
2078     }
2079 
2080     if (!surface->flexibleSurfaceCompatibilityRequested())
2081     {
2082         // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
2083 
2084         bool colorBufferCompat = surfaceConfig->colorBufferType == contextConfig->colorBufferType;
2085         if (!colorBufferCompat)
2086         {
2087             return EglBadMatch() << "Color buffer types are not compatible.";
2088         }
2089 
2090         bool colorCompat = surfaceConfig->redSize == contextConfig->redSize &&
2091                            surfaceConfig->greenSize == contextConfig->greenSize &&
2092                            surfaceConfig->blueSize == contextConfig->blueSize &&
2093                            surfaceConfig->alphaSize == contextConfig->alphaSize &&
2094                            surfaceConfig->luminanceSize == contextConfig->luminanceSize;
2095         if (!colorCompat)
2096         {
2097             return EglBadMatch() << "Color buffer sizes are not compatible.";
2098         }
2099 
2100         bool componentTypeCompat =
2101             surfaceConfig->colorComponentType == contextConfig->colorComponentType;
2102         if (!componentTypeCompat)
2103         {
2104             return EglBadMatch() << "Color buffer component types are not compatible.";
2105         }
2106 
2107         bool dsCompat = surfaceConfig->depthSize == contextConfig->depthSize &&
2108                         surfaceConfig->stencilSize == contextConfig->stencilSize;
2109         if (!dsCompat)
2110         {
2111             return EglBadMatch() << "Depth-stencil buffer types are not compatible.";
2112         }
2113     }
2114 
2115     bool surfaceTypeCompat = (surfaceConfig->surfaceType & contextConfig->surfaceType) != 0;
2116     if (!surfaceTypeCompat)
2117     {
2118         return EglBadMatch() << "Surface type is not compatible.";
2119     }
2120 
2121     return NoError();
2122 }
2123 
ValidateCreateImage(const Display * display,gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)2124 Error ValidateCreateImage(const Display *display,
2125                           gl::Context *context,
2126                           EGLenum target,
2127                           EGLClientBuffer buffer,
2128                           const AttributeMap &attributes)
2129 {
2130 
2131     ANGLE_TRY(ValidateDisplay(display));
2132 
2133     const DisplayExtensions &displayExtensions = display->getExtensions();
2134 
2135     // TODO(geofflang): Complete validation from EGL_KHR_image_base:
2136     // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
2137     // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
2138 
2139     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2140          attributeIter != attributes.end(); attributeIter++)
2141     {
2142         EGLAttrib attribute = attributeIter->first;
2143         EGLAttrib value     = attributeIter->second;
2144 
2145         switch (attribute)
2146         {
2147             case EGL_IMAGE_PRESERVED:
2148                 switch (value)
2149                 {
2150                     case EGL_TRUE:
2151                     case EGL_FALSE:
2152                         break;
2153 
2154                     default:
2155                         return EglBadParameter()
2156                                << "EGL_IMAGE_PRESERVED must be EGL_TRUE or EGL_FALSE.";
2157                 }
2158                 break;
2159 
2160             case EGL_GL_TEXTURE_LEVEL:
2161                 if (!displayExtensions.glTexture2DImage &&
2162                     !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
2163                 {
2164                     return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL cannot be used "
2165                                                 "without KHR_gl_texture_*_image support.";
2166                 }
2167 
2168                 if (value < 0)
2169                 {
2170                     return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL cannot be negative.";
2171                 }
2172                 break;
2173 
2174             case EGL_GL_TEXTURE_ZOFFSET:
2175                 if (!displayExtensions.glTexture3DImage)
2176                 {
2177                     return EglBadParameter() << "EGL_GL_TEXTURE_ZOFFSET cannot be used "
2178                                                 "without KHR_gl_texture_3D_image support.";
2179                 }
2180                 break;
2181 
2182             case EGL_GL_COLORSPACE:
2183                 if (!displayExtensions.glColorspace)
2184                 {
2185                     return EglBadParameter() << "EGL_GL_COLORSPACE cannot be used "
2186                                                 "without EGL_KHR_gl_colorspace support.";
2187                 }
2188                 switch (value)
2189                 {
2190                     case EGL_GL_COLORSPACE_DEFAULT_EXT:
2191                         break;
2192                     default:
2193                         ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
2194                         break;
2195                 }
2196                 break;
2197 
2198             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
2199                 if (!displayExtensions.imageD3D11Texture)
2200                 {
2201                     return EglBadParameter()
2202                            << "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE and EGL_TEXTURE_TYPE_ANGLE cannot "
2203                               "be used without EGL_ANGLE_image_d3d11_texture support.";
2204                 }
2205                 break;
2206 
2207             case EGL_WIDTH:
2208             case EGL_HEIGHT:
2209                 if (target != EGL_LINUX_DMA_BUF_EXT)
2210                 {
2211                     return EglBadParameter()
2212                            << "Parameter cannot be used if target is not EGL_LINUX_DMA_BUF_EXT";
2213                 }
2214                 break;
2215 
2216             case EGL_LINUX_DRM_FOURCC_EXT:
2217             case EGL_DMA_BUF_PLANE0_FD_EXT:
2218             case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
2219             case EGL_DMA_BUF_PLANE0_PITCH_EXT:
2220             case EGL_DMA_BUF_PLANE1_FD_EXT:
2221             case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
2222             case EGL_DMA_BUF_PLANE1_PITCH_EXT:
2223             case EGL_DMA_BUF_PLANE2_FD_EXT:
2224             case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
2225             case EGL_DMA_BUF_PLANE2_PITCH_EXT:
2226                 if (!displayExtensions.imageDmaBufImportEXT)
2227                 {
2228                     return EglBadParameter() << "Parameter cannot be used without "
2229                                                 "EGL_EXT_image_dma_buf_import support.";
2230                 }
2231                 break;
2232 
2233             case EGL_YUV_COLOR_SPACE_HINT_EXT:
2234                 if (!displayExtensions.imageDmaBufImportEXT)
2235                 {
2236                     return EglBadParameter() << "Parameter cannot be used without "
2237                                                 "EGL_EXT_image_dma_buf_import support.";
2238                 }
2239 
2240                 switch (value)
2241                 {
2242                     case EGL_ITU_REC601_EXT:
2243                     case EGL_ITU_REC709_EXT:
2244                     case EGL_ITU_REC2020_EXT:
2245                         break;
2246 
2247                     default:
2248                         return EglBadParameter()
2249                                << "Invalid value for EGL_YUV_COLOR_SPACE_HINT_EXT.";
2250                 }
2251                 break;
2252 
2253             case EGL_SAMPLE_RANGE_HINT_EXT:
2254                 if (!displayExtensions.imageDmaBufImportEXT)
2255                 {
2256                     return EglBadParameter() << "Parameter cannot be used without "
2257                                                 "EGL_EXT_image_dma_buf_import support.";
2258                 }
2259 
2260                 switch (value)
2261                 {
2262                     case EGL_YUV_FULL_RANGE_EXT:
2263                     case EGL_YUV_NARROW_RANGE_EXT:
2264                         break;
2265 
2266                     default:
2267                         return EglBadParameter() << "Invalid value for EGL_SAMPLE_RANGE_HINT_EXT.";
2268                 }
2269                 break;
2270 
2271             case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
2272             case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
2273                 if (!displayExtensions.imageDmaBufImportEXT)
2274                 {
2275                     return EglBadParameter() << "Parameter cannot be used without "
2276                                                 "EGL_EXT_image_dma_buf_import support.";
2277                 }
2278 
2279                 switch (value)
2280                 {
2281                     case EGL_YUV_CHROMA_SITING_0_EXT:
2282                     case EGL_YUV_CHROMA_SITING_0_5_EXT:
2283                         break;
2284 
2285                     default:
2286                         return EglBadParameter()
2287                                << "Invalid value for EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT or "
2288                                   "EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT.";
2289                 }
2290                 break;
2291 
2292             case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
2293             case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
2294             case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
2295             case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
2296             case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
2297             case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
2298             case EGL_DMA_BUF_PLANE3_FD_EXT:
2299             case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
2300             case EGL_DMA_BUF_PLANE3_PITCH_EXT:
2301             case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
2302             case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
2303                 if (!displayExtensions.imageDmaBufImportModifiersEXT)
2304                 {
2305                     return EglBadParameter() << "Parameter cannot be used without "
2306                                                 "EGL_EXT_image_dma_buf_import_modifiers support.";
2307                 }
2308                 break;
2309 
2310             default:
2311                 return EglBadParameter()
2312                        << "invalid attribute: 0x" << std::hex << std::uppercase << attribute;
2313         }
2314     }
2315 
2316     switch (target)
2317     {
2318         case EGL_GL_TEXTURE_2D:
2319         {
2320             if (!displayExtensions.glTexture2DImage)
2321             {
2322                 return EglBadParameter() << "KHR_gl_texture_2D_image not supported.";
2323             }
2324 
2325             if (buffer == 0)
2326             {
2327                 return EglBadParameter() << "buffer cannot reference a 2D texture with the name 0.";
2328             }
2329 
2330             ANGLE_TRY(ValidateContext(display, context));
2331             const gl::Texture *texture =
2332                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2333             if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
2334             {
2335                 return EglBadParameter() << "target is not a 2D texture.";
2336             }
2337 
2338             if (texture->getBoundSurface() != nullptr)
2339             {
2340                 return EglBadAccess() << "texture has a surface bound to it.";
2341             }
2342 
2343             EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
2344             if (texture->getWidth(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0 ||
2345                 texture->getHeight(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0)
2346             {
2347                 return EglBadParameter()
2348                        << "target 2D texture does not have a valid size at specified level.";
2349             }
2350 
2351             ANGLE_TRY(ValidateCreateImageMipLevelCommon(context, texture, level));
2352         }
2353         break;
2354 
2355         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2356         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2357         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2358         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2359         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2360         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2361         {
2362             if (!displayExtensions.glTextureCubemapImage)
2363             {
2364                 return EglBadParameter() << "KHR_gl_texture_cubemap_image not supported.";
2365             }
2366 
2367             if (buffer == 0)
2368             {
2369                 return EglBadParameter()
2370                        << "buffer cannot reference a cubemap texture with the name 0.";
2371             }
2372 
2373             ANGLE_TRY(ValidateContext(display, context));
2374             const gl::Texture *texture =
2375                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2376             if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
2377             {
2378                 return EglBadParameter() << "target is not a cubemap texture.";
2379             }
2380 
2381             if (texture->getBoundSurface() != nullptr)
2382             {
2383                 return EglBadAccess() << "texture has a surface bound to it.";
2384             }
2385 
2386             EGLAttrib level               = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
2387             gl::TextureTarget cubeMapFace = egl_gl::EGLCubeMapTargetToCubeMapTarget(target);
2388             if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
2389                 texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
2390             {
2391                 return EglBadParameter() << "target cubemap texture does not have a valid "
2392                                             "size at specified level and face.";
2393             }
2394 
2395             ANGLE_TRY(ValidateCreateImageMipLevelCommon(context, texture, level));
2396 
2397             if (level == 0 && !texture->isMipmapComplete() &&
2398                 CubeTextureHasUnspecifiedLevel0Face(texture))
2399             {
2400                 return EglBadParameter() << "if level is zero and the texture is incomplete, "
2401                                             "it must have all of its faces specified at level "
2402                                             "zero.";
2403             }
2404         }
2405         break;
2406 
2407         case EGL_GL_TEXTURE_3D:
2408         {
2409             if (!displayExtensions.glTexture3DImage)
2410             {
2411                 return EglBadParameter() << "KHR_gl_texture_3D_image not supported.";
2412             }
2413 
2414             if (buffer == 0)
2415             {
2416                 return EglBadParameter() << "buffer cannot reference a 3D texture with the name 0.";
2417             }
2418 
2419             ANGLE_TRY(ValidateContext(display, context));
2420             const gl::Texture *texture =
2421                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2422             if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
2423             {
2424                 return EglBadParameter() << "target is not a 3D texture.";
2425             }
2426 
2427             if (texture->getBoundSurface() != nullptr)
2428             {
2429                 return EglBadAccess() << "texture has a surface bound to it.";
2430             }
2431 
2432             EGLAttrib level   = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
2433             EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET, 0);
2434             if (texture->getWidth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
2435                 texture->getHeight(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
2436                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0)
2437             {
2438                 return EglBadParameter()
2439                        << "target 3D texture does not have a valid size at specified level.";
2440             }
2441 
2442             if (static_cast<size_t>(zOffset) >=
2443                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)))
2444             {
2445                 return EglBadParameter() << "target 3D texture does not have enough layers "
2446                                             "for the specified Z offset at the specified "
2447                                             "level.";
2448             }
2449 
2450             ANGLE_TRY(ValidateCreateImageMipLevelCommon(context, texture, level));
2451         }
2452         break;
2453 
2454         case EGL_GL_RENDERBUFFER:
2455         {
2456             if (!displayExtensions.glRenderbufferImage)
2457             {
2458                 return EglBadParameter() << "KHR_gl_renderbuffer_image not supported.";
2459             }
2460 
2461             if (attributes.contains(EGL_GL_TEXTURE_LEVEL))
2462             {
2463                 return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL cannot be used in "
2464                                             "conjunction with a renderbuffer target.";
2465             }
2466 
2467             if (buffer == 0)
2468             {
2469                 return EglBadParameter()
2470                        << "buffer cannot reference a renderbuffer with the name 0.";
2471             }
2472 
2473             ANGLE_TRY(ValidateContext(display, context));
2474             const gl::Renderbuffer *renderbuffer =
2475                 context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2476             if (renderbuffer == nullptr)
2477             {
2478                 return EglBadParameter() << "target is not a renderbuffer.";
2479             }
2480 
2481             if (renderbuffer->getSamples() > 0)
2482             {
2483                 return EglBadParameter() << "target renderbuffer cannot be multisampled.";
2484             }
2485         }
2486         break;
2487 
2488         case EGL_NATIVE_BUFFER_ANDROID:
2489         {
2490             if (!displayExtensions.imageNativeBuffer)
2491             {
2492                 return EglBadParameter() << "EGL_ANDROID_image_native_buffer not supported.";
2493             }
2494 
2495             if (context != nullptr)
2496             {
2497                 return EglBadContext() << "ctx must be EGL_NO_CONTEXT.";
2498             }
2499 
2500             ANGLE_TRY(display->validateImageClientBuffer(context, target, buffer, attributes));
2501         }
2502         break;
2503 
2504         case EGL_D3D11_TEXTURE_ANGLE:
2505             if (!displayExtensions.imageD3D11Texture)
2506             {
2507                 return EglBadParameter() << "EGL_ANGLE_image_d3d11_texture not supported.";
2508             }
2509 
2510             if (context != nullptr)
2511             {
2512                 return EglBadContext() << "ctx must be EGL_NO_CONTEXT.";
2513             }
2514 
2515             ANGLE_TRY(display->validateImageClientBuffer(context, target, buffer, attributes));
2516             break;
2517 
2518         case EGL_LINUX_DMA_BUF_EXT:
2519             if (!displayExtensions.imageDmaBufImportEXT)
2520             {
2521                 return EglBadParameter() << "EGL_EXT_image_dma_buf_import not supported.";
2522             }
2523 
2524             if (context != nullptr)
2525             {
2526                 return EglBadContext() << "ctx must be EGL_NO_CONTEXT.";
2527             }
2528 
2529             if (buffer != nullptr)
2530             {
2531                 return EglBadParameter() << "buffer must be NULL.";
2532             }
2533 
2534             {
2535                 EGLenum kRequiredParameters[] = {EGL_WIDTH,
2536                                                  EGL_HEIGHT,
2537                                                  EGL_LINUX_DRM_FOURCC_EXT,
2538                                                  EGL_DMA_BUF_PLANE0_FD_EXT,
2539                                                  EGL_DMA_BUF_PLANE0_OFFSET_EXT,
2540                                                  EGL_DMA_BUF_PLANE0_PITCH_EXT};
2541                 for (EGLenum requiredParameter : kRequiredParameters)
2542                 {
2543                     if (!attributes.contains(requiredParameter))
2544                     {
2545                         return EglBadParameter()
2546                                << "Missing required parameter " << gl::FmtHex(requiredParameter)
2547                                << " for image target EGL_LINUX_DMA_BUF_EXT.";
2548                     }
2549                 }
2550 
2551                 bool containPlane0ModifierLo =
2552                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT);
2553                 bool containPlane0ModifierHi =
2554                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT);
2555                 bool containPlane1ModifierLo =
2556                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT);
2557                 bool containPlane1ModifierHi =
2558                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT);
2559                 bool containPlane2ModifierLo =
2560                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT);
2561                 bool containPlane2ModifierHi =
2562                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT);
2563                 bool containPlane3ModifierLo =
2564                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT);
2565                 bool containPlane3ModifierHi =
2566                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT);
2567                 if ((containPlane0ModifierLo ^ containPlane0ModifierHi) ||
2568                     (containPlane1ModifierLo ^ containPlane1ModifierHi) ||
2569                     (containPlane2ModifierLo ^ containPlane2ModifierHi) ||
2570                     (containPlane3ModifierLo ^ containPlane3ModifierHi))
2571                 {
2572                     return EglBadParameter()
2573                            << "the list of attributes contains EGL_DMA_BUF_PLANE*_MODIFIER_LO_EXT "
2574                               "but not EGL_DMA_BUF_PLANE*_MODIFIER_HI_EXT or vice versa.";
2575                 }
2576             }
2577             break;
2578 
2579         default:
2580             return EglBadParameter()
2581                    << "invalid target: 0x" << std::hex << std::uppercase << target;
2582     }
2583 
2584     if (attributes.contains(EGL_GL_TEXTURE_ZOFFSET) && target != EGL_GL_TEXTURE_3D)
2585     {
2586         return EglBadParameter() << "EGL_GL_TEXTURE_ZOFFSET must be used with a 3D texture target.";
2587     }
2588 
2589     return NoError();
2590 }
2591 
ValidateDestroyImage(const Display * display,const Image * image)2592 Error ValidateDestroyImage(const Display *display, const Image *image)
2593 {
2594     ANGLE_TRY(ValidateImage(display, image));
2595 
2596     return NoError();
2597 }
2598 
ValidateCreateImageKHR(const Display * display,gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)2599 Error ValidateCreateImageKHR(const Display *display,
2600                              gl::Context *context,
2601                              EGLenum target,
2602                              EGLClientBuffer buffer,
2603                              const AttributeMap &attributes)
2604 {
2605     ANGLE_TRY(ValidateDisplay(display));
2606 
2607     if (!display->getExtensions().imageBase && !display->getExtensions().image)
2608     {
2609         // It is out of spec what happens when calling an extension function when the extension is
2610         // not available.
2611         // EGL_BAD_DISPLAY seems like a reasonable error.
2612         return EglBadDisplay() << "EGL_KHR_image not supported.";
2613     }
2614 
2615     return ValidateCreateImage(display, context, target, buffer, attributes);
2616 }
2617 
ValidateDestroyImageKHR(const Display * display,const Image * image)2618 Error ValidateDestroyImageKHR(const Display *display, const Image *image)
2619 {
2620     ANGLE_TRY(ValidateImage(display, image));
2621 
2622     if (!display->getExtensions().imageBase && !display->getExtensions().image)
2623     {
2624         // It is out of spec what happens when calling an extension function when the extension is
2625         // not available.
2626         // EGL_BAD_DISPLAY seems like a reasonable error.
2627         return EglBadDisplay();
2628     }
2629 
2630     return NoError();
2631 }
2632 
ValidateCreateDeviceANGLE(EGLint device_type,void * native_device,const EGLAttrib * attrib_list)2633 Error ValidateCreateDeviceANGLE(EGLint device_type,
2634                                 void *native_device,
2635                                 const EGLAttrib *attrib_list)
2636 {
2637     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
2638     if (!clientExtensions.deviceCreation)
2639     {
2640         return EglBadAccess() << "Device creation extension not active";
2641     }
2642 
2643     if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
2644     {
2645         return EglBadAttribute() << "Invalid attrib_list parameter";
2646     }
2647 
2648     switch (device_type)
2649     {
2650         case EGL_D3D11_DEVICE_ANGLE:
2651             if (!clientExtensions.deviceCreationD3D11)
2652             {
2653                 return EglBadAttribute() << "D3D11 device creation extension not active";
2654             }
2655             break;
2656         default:
2657             return EglBadAttribute() << "Invalid device_type parameter";
2658     }
2659 
2660     return NoError();
2661 }
2662 
ValidateReleaseDeviceANGLE(Device * device)2663 Error ValidateReleaseDeviceANGLE(Device *device)
2664 {
2665     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
2666     if (!clientExtensions.deviceCreation)
2667     {
2668         return EglBadAccess() << "Device creation extension not active";
2669     }
2670 
2671     if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
2672     {
2673         return EglBadDevice() << "Invalid device parameter";
2674     }
2675 
2676     Display *owningDisplay = device->getOwningDisplay();
2677     if (owningDisplay != nullptr)
2678     {
2679         return EglBadDevice() << "Device must have been created using eglCreateDevice";
2680     }
2681 
2682     return NoError();
2683 }
2684 
ValidateCreateSyncBase(const Display * display,EGLenum type,const AttributeMap & attribs,const Display * currentDisplay,const gl::Context * currentContext,bool isExt)2685 Error ValidateCreateSyncBase(const Display *display,
2686                              EGLenum type,
2687                              const AttributeMap &attribs,
2688                              const Display *currentDisplay,
2689                              const gl::Context *currentContext,
2690                              bool isExt)
2691 {
2692     ANGLE_TRY(ValidateDisplay(display));
2693 
2694     switch (type)
2695     {
2696         case EGL_SYNC_FENCE_KHR:
2697             if (!attribs.isEmpty())
2698             {
2699                 return EglBadAttribute() << "Invalid attribute";
2700             }
2701             break;
2702 
2703         case EGL_SYNC_NATIVE_FENCE_ANDROID:
2704             if (!display->getExtensions().nativeFenceSyncANDROID)
2705             {
2706                 return EglBadDisplay()
2707                        << "EGL_ANDROID_native_fence_sync extension is not available.";
2708             }
2709 
2710             for (const auto &attributeIter : attribs)
2711             {
2712                 EGLAttrib attribute = attributeIter.first;
2713 
2714                 switch (attribute)
2715                 {
2716                     case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
2717                         break;
2718 
2719                     default:
2720                         return EglBadAttribute() << "Invalid attribute";
2721                 }
2722             }
2723             break;
2724 
2725         default:
2726             if (isExt)
2727             {
2728                 return EglBadAttribute() << "Invalid type parameter";
2729             }
2730             else
2731             {
2732                 return EglBadParameter() << "Invalid type parameter";
2733             }
2734     }
2735 
2736     if (display != currentDisplay)
2737     {
2738         return EglBadMatch() << "CreateSync can only be called on the current display";
2739     }
2740 
2741     ANGLE_TRY(ValidateContext(currentDisplay, currentContext));
2742 
2743     if (!currentContext->getExtensions().eglSyncOES)
2744     {
2745         return EglBadMatch() << "EGL_SYNC_FENCE_KHR cannot be used without "
2746                                 "GL_OES_EGL_sync support.";
2747     }
2748 
2749     return NoError();
2750 }
2751 
ValidateGetSyncAttribBase(const Display * display,const Sync * sync,EGLint attribute)2752 Error ValidateGetSyncAttribBase(const Display *display, const Sync *sync, EGLint attribute)
2753 {
2754     ANGLE_TRY(ValidateSync(display, sync));
2755 
2756     switch (attribute)
2757     {
2758         case EGL_SYNC_CONDITION_KHR:
2759             switch (sync->getType())
2760             {
2761                 case EGL_SYNC_FENCE_KHR:
2762                 case EGL_SYNC_NATIVE_FENCE_ANDROID:
2763                     break;
2764 
2765                 default:
2766                     return EglBadAttribute()
2767                            << "EGL_SYNC_CONDITION_KHR is not valid for this sync type.";
2768             }
2769             break;
2770 
2771         // The following attributes are accepted by all types
2772         case EGL_SYNC_TYPE_KHR:
2773         case EGL_SYNC_STATUS_KHR:
2774             break;
2775 
2776         default:
2777             return EglBadAttribute() << "Invalid attribute";
2778     }
2779 
2780     return NoError();
2781 }
2782 
ValidateCreateSyncKHR(const Display * display,EGLenum type,const AttributeMap & attribs,const Display * currentDisplay,const gl::Context * currentContext)2783 Error ValidateCreateSyncKHR(const Display *display,
2784                             EGLenum type,
2785                             const AttributeMap &attribs,
2786                             const Display *currentDisplay,
2787                             const gl::Context *currentContext)
2788 {
2789     ANGLE_TRY(ValidateDisplay(display));
2790 
2791     const DisplayExtensions &extensions = display->getExtensions();
2792     if (!extensions.fenceSync)
2793     {
2794         return EglBadAccess() << "EGL_KHR_fence_sync extension is not available";
2795     }
2796 
2797     return ValidateCreateSyncBase(display, type, attribs, currentDisplay, currentContext, true);
2798 }
2799 
ValidateCreateSync(const Display * display,EGLenum type,const AttributeMap & attribs,const Display * currentDisplay,const gl::Context * currentContext)2800 Error ValidateCreateSync(const Display *display,
2801                          EGLenum type,
2802                          const AttributeMap &attribs,
2803                          const Display *currentDisplay,
2804                          const gl::Context *currentContext)
2805 {
2806     return ValidateCreateSyncBase(display, type, attribs, currentDisplay, currentContext, false);
2807 }
2808 
ValidateDestroySync(const Display * display,const Sync * sync)2809 Error ValidateDestroySync(const Display *display, const Sync *sync)
2810 {
2811     ANGLE_TRY(ValidateSync(display, sync));
2812     return NoError();
2813 }
2814 
ValidateClientWaitSync(const Display * display,const Sync * sync,EGLint flags,EGLTime timeout)2815 Error ValidateClientWaitSync(const Display *display,
2816                              const Sync *sync,
2817                              EGLint flags,
2818                              EGLTime timeout)
2819 {
2820     ANGLE_TRY(ValidateSync(display, sync));
2821     return NoError();
2822 }
2823 
ValidateWaitSync(const Display * display,const gl::Context * context,const Sync * sync,EGLint flags)2824 Error ValidateWaitSync(const Display *display,
2825                        const gl::Context *context,
2826                        const Sync *sync,
2827                        EGLint flags)
2828 {
2829     ANGLE_TRY(ValidateDisplay(display));
2830 
2831     const DisplayExtensions &extensions = display->getExtensions();
2832     if (!extensions.waitSync)
2833     {
2834         return EglBadAccess() << "EGL_KHR_wait_sync extension is not available";
2835     }
2836 
2837     ANGLE_TRY(ValidateSync(display, sync));
2838 
2839     if (context == nullptr)
2840     {
2841         return EglBadMatch() << "No context is current.";
2842     }
2843 
2844     if (!context->getExtensions().eglSyncOES)
2845     {
2846         return EglBadMatch() << "Server-side waits cannot be performed without "
2847                                 "GL_OES_EGL_sync support.";
2848     }
2849 
2850     if (flags != 0)
2851     {
2852         return EglBadParameter() << "flags must be zero";
2853     }
2854 
2855     return NoError();
2856 }
2857 
ValidateGetSyncAttribKHR(const Display * display,const Sync * sync,EGLint attribute,EGLint * value)2858 Error ValidateGetSyncAttribKHR(const Display *display,
2859                                const Sync *sync,
2860                                EGLint attribute,
2861                                EGLint *value)
2862 {
2863     if (value == nullptr)
2864     {
2865         return EglBadParameter() << "Invalid value parameter";
2866     }
2867     return ValidateGetSyncAttribBase(display, sync, attribute);
2868 }
2869 
ValidateGetSyncAttrib(const Display * display,const Sync * sync,EGLint attribute,EGLAttrib * value)2870 Error ValidateGetSyncAttrib(const Display *display,
2871                             const Sync *sync,
2872                             EGLint attribute,
2873                             EGLAttrib *value)
2874 {
2875     if (value == nullptr)
2876     {
2877         return EglBadParameter() << "Invalid value parameter";
2878     }
2879     return ValidateGetSyncAttribBase(display, sync, attribute);
2880 }
2881 
ValidateCreateStreamKHR(const Display * display,const AttributeMap & attributes)2882 Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes)
2883 {
2884     ANGLE_TRY(ValidateDisplay(display));
2885 
2886     const DisplayExtensions &displayExtensions = display->getExtensions();
2887     if (!displayExtensions.stream)
2888     {
2889         return EglBadAlloc() << "Stream extension not active";
2890     }
2891 
2892     for (const auto &attributeIter : attributes)
2893     {
2894         EGLAttrib attribute = attributeIter.first;
2895         EGLAttrib value     = attributeIter.second;
2896 
2897         ANGLE_TRY(ValidateStreamAttribute(attribute, value, displayExtensions));
2898     }
2899 
2900     return NoError();
2901 }
2902 
ValidateDestroyStreamKHR(const Display * display,const Stream * stream)2903 Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream)
2904 {
2905     ANGLE_TRY(ValidateStream(display, stream));
2906     return NoError();
2907 }
2908 
ValidateStreamAttribKHR(const Display * display,const Stream * stream,EGLint attribute,EGLint value)2909 Error ValidateStreamAttribKHR(const Display *display,
2910                               const Stream *stream,
2911                               EGLint attribute,
2912                               EGLint value)
2913 {
2914     ANGLE_TRY(ValidateStream(display, stream));
2915 
2916     if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
2917     {
2918         return EglBadState() << "Bad stream state";
2919     }
2920 
2921     return ValidateStreamAttribute(attribute, value, display->getExtensions());
2922 }
2923 
ValidateQueryStreamKHR(const Display * display,const Stream * stream,EGLenum attribute,EGLint * value)2924 Error ValidateQueryStreamKHR(const Display *display,
2925                              const Stream *stream,
2926                              EGLenum attribute,
2927                              EGLint *value)
2928 {
2929     ANGLE_TRY(ValidateStream(display, stream));
2930 
2931     switch (attribute)
2932     {
2933         case EGL_STREAM_STATE_KHR:
2934         case EGL_CONSUMER_LATENCY_USEC_KHR:
2935             break;
2936         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
2937             if (!display->getExtensions().streamConsumerGLTexture)
2938             {
2939                 return EglBadAttribute() << "Consumer GLTexture extension not active";
2940             }
2941             break;
2942         default:
2943             return EglBadAttribute() << "Invalid attribute";
2944     }
2945 
2946     return NoError();
2947 }
2948 
ValidateQueryStreamu64KHR(const Display * display,const Stream * stream,EGLenum attribute,EGLuint64KHR * value)2949 Error ValidateQueryStreamu64KHR(const Display *display,
2950                                 const Stream *stream,
2951                                 EGLenum attribute,
2952                                 EGLuint64KHR *value)
2953 {
2954     ANGLE_TRY(ValidateStream(display, stream));
2955 
2956     switch (attribute)
2957     {
2958         case EGL_CONSUMER_FRAME_KHR:
2959         case EGL_PRODUCER_FRAME_KHR:
2960             break;
2961         default:
2962             return EglBadAttribute() << "Invalid attribute";
2963     }
2964 
2965     return NoError();
2966 }
2967 
ValidateStreamConsumerGLTextureExternalKHR(const Display * display,gl::Context * context,const Stream * stream)2968 Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
2969                                                  gl::Context *context,
2970                                                  const Stream *stream)
2971 {
2972     ANGLE_TRY(ValidateContext(display, context));
2973 
2974     const DisplayExtensions &displayExtensions = display->getExtensions();
2975     if (!displayExtensions.streamConsumerGLTexture)
2976     {
2977         return EglBadAccess() << "Stream consumer extension not active";
2978     }
2979 
2980     if (!context->getExtensions().eglStreamConsumerExternalNV)
2981     {
2982         return EglBadAccess() << "EGL stream consumer external GL extension not enabled";
2983     }
2984 
2985     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
2986     {
2987         return EglBadStream() << "Invalid stream";
2988     }
2989 
2990     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
2991     {
2992         return EglBadState() << "Invalid stream state";
2993     }
2994 
2995     // Lookup the texture and ensure it is correct
2996     gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
2997     if (texture == nullptr || texture->id().value == 0)
2998     {
2999         return EglBadAccess() << "No external texture bound";
3000     }
3001 
3002     return NoError();
3003 }
3004 
ValidateStreamConsumerAcquireKHR(const Display * display,gl::Context * context,const Stream * stream)3005 Error ValidateStreamConsumerAcquireKHR(const Display *display,
3006                                        gl::Context *context,
3007                                        const Stream *stream)
3008 {
3009     ANGLE_TRY(ValidateDisplay(display));
3010 
3011     const DisplayExtensions &displayExtensions = display->getExtensions();
3012     if (!displayExtensions.streamConsumerGLTexture)
3013     {
3014         return EglBadAccess() << "Stream consumer extension not active";
3015     }
3016 
3017     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
3018     {
3019         return EglBadStream() << "Invalid stream";
3020     }
3021 
3022     if (!context)
3023     {
3024         return EglBadAccess() << "No GL context current to calling thread.";
3025     }
3026 
3027     ANGLE_TRY(ValidateContext(display, context));
3028 
3029     if (!stream->isConsumerBoundToContext(context))
3030     {
3031         return EglBadAccess() << "Current GL context not associated with stream consumer";
3032     }
3033 
3034     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
3035         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
3036     {
3037         return EglBadAccess() << "Invalid stream consumer type";
3038     }
3039 
3040     // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
3041     // However, the timeout is effectively ignored since it has no useful functionality with the
3042     // current producers that are implemented, so we don't allow that state
3043     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
3044         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
3045     {
3046         return EglBadState() << "Invalid stream state";
3047     }
3048 
3049     return NoError();
3050 }
3051 
ValidateStreamConsumerReleaseKHR(const Display * display,gl::Context * context,const Stream * stream)3052 Error ValidateStreamConsumerReleaseKHR(const Display *display,
3053                                        gl::Context *context,
3054                                        const Stream *stream)
3055 {
3056     ANGLE_TRY(ValidateDisplay(display));
3057 
3058     const DisplayExtensions &displayExtensions = display->getExtensions();
3059     if (!displayExtensions.streamConsumerGLTexture)
3060     {
3061         return EglBadAccess() << "Stream consumer extension not active";
3062     }
3063 
3064     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
3065     {
3066         return EglBadStream() << "Invalid stream";
3067     }
3068 
3069     if (!context)
3070     {
3071         return EglBadAccess() << "No GL context current to calling thread.";
3072     }
3073 
3074     ANGLE_TRY(ValidateContext(display, context));
3075 
3076     if (!stream->isConsumerBoundToContext(context))
3077     {
3078         return EglBadAccess() << "Current GL context not associated with stream consumer";
3079     }
3080 
3081     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
3082         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
3083     {
3084         return EglBadAccess() << "Invalid stream consumer type";
3085     }
3086 
3087     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
3088         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
3089     {
3090         return EglBadState() << "Invalid stream state";
3091     }
3092 
3093     return NoError();
3094 }
3095 
ValidateStreamConsumerGLTextureExternalAttribsNV(const Display * display,gl::Context * context,const Stream * stream,const AttributeMap & attribs)3096 Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
3097                                                        gl::Context *context,
3098                                                        const Stream *stream,
3099                                                        const AttributeMap &attribs)
3100 {
3101     ANGLE_TRY(ValidateDisplay(display));
3102 
3103     const DisplayExtensions &displayExtensions = display->getExtensions();
3104     if (!displayExtensions.streamConsumerGLTexture)
3105     {
3106         return EglBadAccess() << "Stream consumer extension not active";
3107     }
3108 
3109     ANGLE_TRY(ValidateContext(display, context));
3110 
3111     // Although technically not a requirement in spec, the context needs to be checked for support
3112     // for external textures or future logic will cause assertations. This extension is also
3113     // effectively useless without external textures.
3114     if (!context->getExtensions().eglStreamConsumerExternalNV)
3115     {
3116         return EglBadAccess() << "EGL stream consumer external GL extension not enabled";
3117     }
3118 
3119     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
3120     {
3121         return EglBadStream() << "Invalid stream";
3122     }
3123 
3124     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
3125     {
3126         return EglBadState() << "Invalid stream state";
3127     }
3128 
3129     const gl::Caps &glCaps = context->getCaps();
3130 
3131     EGLAttrib colorBufferType = EGL_RGB_BUFFER;
3132     EGLAttrib planeCount      = -1;
3133     EGLAttrib plane[3];
3134     for (int i = 0; i < 3; i++)
3135     {
3136         plane[i] = -1;
3137     }
3138     for (const auto &attributeIter : attribs)
3139     {
3140         EGLAttrib attribute = attributeIter.first;
3141         EGLAttrib value     = attributeIter.second;
3142 
3143         switch (attribute)
3144         {
3145             case EGL_COLOR_BUFFER_TYPE:
3146                 if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
3147                 {
3148                     return EglBadParameter() << "Invalid color buffer type";
3149                 }
3150                 colorBufferType = value;
3151                 break;
3152             case EGL_YUV_NUMBER_OF_PLANES_EXT:
3153                 // planeCount = -1 is a tag for the default plane count so the value must be checked
3154                 // to be positive here to ensure future logic doesn't break on invalid negative
3155                 // inputs
3156                 if (value < 0)
3157                 {
3158                     return EglBadMatch() << "Invalid plane count";
3159                 }
3160                 planeCount = value;
3161                 break;
3162             default:
3163                 if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
3164                     attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
3165                 {
3166                     if ((value < 0 ||
3167                          value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
3168                         value != EGL_NONE)
3169                     {
3170                         return EglBadAccess() << "Invalid texture unit";
3171                     }
3172                     plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
3173                 }
3174                 else
3175                 {
3176                     return EglBadAttribute() << "Invalid attribute";
3177                 }
3178         }
3179     }
3180 
3181     if (colorBufferType == EGL_RGB_BUFFER)
3182     {
3183         if (planeCount > 0)
3184         {
3185             return EglBadMatch() << "Plane count must be 0 for RGB buffer";
3186         }
3187         for (int i = 0; i < 3; i++)
3188         {
3189             if (plane[i] != -1)
3190             {
3191                 return EglBadMatch() << "Planes cannot be specified";
3192             }
3193         }
3194 
3195         // Lookup the texture and ensure it is correct
3196         gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
3197         if (texture == nullptr || texture->id().value == 0)
3198         {
3199             return EglBadAccess() << "No external texture bound";
3200         }
3201     }
3202     else
3203     {
3204         if (planeCount == -1)
3205         {
3206             planeCount = 2;
3207         }
3208         if (planeCount < 1 || planeCount > 3)
3209         {
3210             return EglBadMatch() << "Invalid YUV plane count";
3211         }
3212         for (EGLAttrib i = planeCount; i < 3; i++)
3213         {
3214             if (plane[i] != -1)
3215             {
3216                 return EglBadMatch() << "Invalid plane specified";
3217             }
3218         }
3219 
3220         // Set to ensure no texture is referenced more than once
3221         std::set<gl::Texture *> textureSet;
3222         for (EGLAttrib i = 0; i < planeCount; i++)
3223         {
3224             if (plane[i] == -1)
3225             {
3226                 return EglBadMatch() << "Not all planes specified";
3227             }
3228             if (plane[i] != EGL_NONE)
3229             {
3230                 gl::Texture *texture = context->getState().getSamplerTexture(
3231                     static_cast<unsigned int>(plane[i]), gl::TextureType::External);
3232                 if (texture == nullptr || texture->id().value == 0)
3233                 {
3234                     return EglBadAccess()
3235                            << "No external texture bound at one or more specified texture units";
3236                 }
3237                 if (textureSet.find(texture) != textureSet.end())
3238                 {
3239                     return EglBadAccess() << "Multiple planes bound to same texture object";
3240                 }
3241                 textureSet.insert(texture);
3242             }
3243         }
3244     }
3245 
3246     return NoError();
3247 }
3248 
ValidateCreateStreamProducerD3DTextureANGLE(const Display * display,const Stream * stream,const AttributeMap & attribs)3249 Error ValidateCreateStreamProducerD3DTextureANGLE(const Display *display,
3250                                                   const Stream *stream,
3251                                                   const AttributeMap &attribs)
3252 {
3253     ANGLE_TRY(ValidateDisplay(display));
3254 
3255     const DisplayExtensions &displayExtensions = display->getExtensions();
3256     if (!displayExtensions.streamProducerD3DTexture)
3257     {
3258         return EglBadAccess() << "Stream producer extension not active";
3259     }
3260 
3261     ANGLE_TRY(ValidateStream(display, stream));
3262 
3263     if (!attribs.isEmpty())
3264     {
3265         return EglBadAttribute() << "Invalid attribute";
3266     }
3267 
3268     if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
3269     {
3270         return EglBadState() << "Stream not in connecting state";
3271     }
3272 
3273     switch (stream->getConsumerType())
3274     {
3275         case Stream::ConsumerType::GLTextureYUV:
3276             if (stream->getPlaneCount() != 2)
3277             {
3278                 return EglBadMatch() << "Incompatible stream consumer type";
3279             }
3280             break;
3281 
3282         case Stream::ConsumerType::GLTextureRGB:
3283             if (stream->getPlaneCount() != 1)
3284             {
3285                 return EglBadMatch() << "Incompatible stream consumer type";
3286             }
3287             break;
3288 
3289         default:
3290             return EglBadMatch() << "Incompatible stream consumer type";
3291     }
3292 
3293     return NoError();
3294 }
3295 
ValidateStreamPostD3DTextureANGLE(const Display * display,const Stream * stream,void * texture,const AttributeMap & attribs)3296 Error ValidateStreamPostD3DTextureANGLE(const Display *display,
3297                                         const Stream *stream,
3298                                         void *texture,
3299                                         const AttributeMap &attribs)
3300 {
3301     ANGLE_TRY(ValidateDisplay(display));
3302 
3303     const DisplayExtensions &displayExtensions = display->getExtensions();
3304     if (!displayExtensions.streamProducerD3DTexture)
3305     {
3306         return EglBadAccess() << "Stream producer extension not active";
3307     }
3308 
3309     ANGLE_TRY(ValidateStream(display, stream));
3310 
3311     for (auto &attributeIter : attribs)
3312     {
3313         EGLAttrib attribute = attributeIter.first;
3314         EGLAttrib value     = attributeIter.second;
3315 
3316         switch (attribute)
3317         {
3318             case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
3319                 if (value < 0)
3320                 {
3321                     return EglBadParameter() << "Invalid subresource index";
3322                 }
3323                 break;
3324             case EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG:
3325                 if (value < 0)
3326                 {
3327                     return EglBadParameter() << "Invalid plane offset";
3328                 }
3329                 break;
3330             default:
3331                 return EglBadAttribute() << "Invalid attribute";
3332         }
3333     }
3334 
3335     if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
3336         stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
3337         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
3338     {
3339         return EglBadState() << "Stream not fully configured";
3340     }
3341 
3342     if (stream->getProducerType() != Stream::ProducerType::D3D11Texture)
3343     {
3344         return EglBadMatch() << "Incompatible stream producer";
3345     }
3346 
3347     if (texture == nullptr)
3348     {
3349         return EglBadParameter() << "Texture is null";
3350     }
3351 
3352     return stream->validateD3D11Texture(texture, attribs);
3353 }
3354 
ValidateSyncControlCHROMIUM(const Display * display,const Surface * eglSurface)3355 Error ValidateSyncControlCHROMIUM(const Display *display, const Surface *eglSurface)
3356 {
3357     ANGLE_TRY(ValidateDisplay(display));
3358     ANGLE_TRY(ValidateSurface(display, eglSurface));
3359 
3360     const DisplayExtensions &displayExtensions = display->getExtensions();
3361     if (!displayExtensions.syncControlCHROMIUM)
3362     {
3363         return EglBadAccess() << "syncControlCHROMIUM extension not active";
3364     }
3365 
3366     return NoError();
3367 }
3368 
ValidateSyncControlRateANGLE(const Display * display,const Surface * eglSurface)3369 Error ValidateSyncControlRateANGLE(const Display *display, const Surface *eglSurface)
3370 {
3371     ANGLE_TRY(ValidateDisplay(display));
3372     ANGLE_TRY(ValidateSurface(display, eglSurface));
3373 
3374     const DisplayExtensions &displayExtensions = display->getExtensions();
3375     if (!displayExtensions.syncControlRateANGLE)
3376     {
3377         return EglBadAccess() << "syncControlRateANGLE extension not active";
3378     }
3379 
3380     return NoError();
3381 }
3382 
ValidateGetMscRateANGLE(const Display * display,const Surface * eglSurface,const EGLint * numerator,const EGLint * denominator)3383 Error ValidateGetMscRateANGLE(const Display *display,
3384                               const Surface *eglSurface,
3385                               const EGLint *numerator,
3386                               const EGLint *denominator)
3387 {
3388     ANGLE_TRY(ValidateSyncControlRateANGLE(display, eglSurface));
3389 
3390     if (numerator == nullptr)
3391     {
3392         return EglBadParameter() << "numerator is null";
3393     }
3394     if (denominator == nullptr)
3395     {
3396         return EglBadParameter() << "denominator is null";
3397     }
3398 
3399     return NoError();
3400 }
3401 
ValidateGetSyncValuesCHROMIUM(const Display * display,const Surface * eglSurface,const EGLuint64KHR * ust,const EGLuint64KHR * msc,const EGLuint64KHR * sbc)3402 Error ValidateGetSyncValuesCHROMIUM(const Display *display,
3403                                     const Surface *eglSurface,
3404                                     const EGLuint64KHR *ust,
3405                                     const EGLuint64KHR *msc,
3406                                     const EGLuint64KHR *sbc)
3407 {
3408     ANGLE_TRY(ValidateSyncControlCHROMIUM(display, eglSurface));
3409 
3410     if (ust == nullptr)
3411     {
3412         return EglBadParameter() << "ust is null";
3413     }
3414     if (msc == nullptr)
3415     {
3416         return EglBadParameter() << "msc is null";
3417     }
3418     if (sbc == nullptr)
3419     {
3420         return EglBadParameter() << "sbc is null";
3421     }
3422 
3423     return NoError();
3424 }
3425 
ValidateDestroySurface(const Display * display,const Surface * surface,const EGLSurface eglSurface)3426 Error ValidateDestroySurface(const Display *display,
3427                              const Surface *surface,
3428                              const EGLSurface eglSurface)
3429 {
3430     ANGLE_TRY(ValidateSurface(display, surface));
3431 
3432     if (eglSurface == EGL_NO_SURFACE)
3433     {
3434         return EglBadSurface();
3435     }
3436 
3437     return NoError();
3438 }
3439 
ValidateDestroyContext(const Display * display,const gl::Context * glCtx,const EGLContext eglCtx)3440 Error ValidateDestroyContext(const Display *display,
3441                              const gl::Context *glCtx,
3442                              const EGLContext eglCtx)
3443 {
3444     ANGLE_TRY(ValidateContext(display, glCtx));
3445 
3446     if (eglCtx == EGL_NO_CONTEXT)
3447     {
3448         return EglBadContext();
3449     }
3450 
3451     return NoError();
3452 }
3453 
ValidateSwapBuffers(Thread * thread,const Display * display,const Surface * eglSurface)3454 Error ValidateSwapBuffers(Thread *thread, const Display *display, const Surface *eglSurface)
3455 {
3456     ANGLE_TRY(ValidateSurface(display, eglSurface));
3457 
3458     if (display->isDeviceLost())
3459     {
3460         return EglContextLost();
3461     }
3462 
3463     if (eglSurface == EGL_NO_SURFACE || !thread->getContext() ||
3464         thread->getCurrentDrawSurface() != eglSurface)
3465     {
3466         return EglBadSurface();
3467     }
3468 
3469     return NoError();
3470 }
3471 
ValidateSwapBuffersWithDamageKHR(const Display * display,const Surface * surface,EGLint * rects,EGLint n_rects)3472 Error ValidateSwapBuffersWithDamageKHR(const Display *display,
3473                                        const Surface *surface,
3474                                        EGLint *rects,
3475                                        EGLint n_rects)
3476 {
3477     ANGLE_TRY(ValidateSurface(display, surface));
3478 
3479     if (!display->getExtensions().swapBuffersWithDamage)
3480     {
3481         // It is out of spec what happens when calling an extension function when the extension is
3482         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
3483         return EglBadDisplay() << "EGL_KHR_swap_buffers_with_damage is not available.";
3484     }
3485 
3486     if (surface == EGL_NO_SURFACE)
3487     {
3488         return EglBadSurface() << "Swap surface cannot be EGL_NO_SURFACE.";
3489     }
3490 
3491     if (n_rects < 0)
3492     {
3493         return EglBadParameter() << "n_rects cannot be negative.";
3494     }
3495 
3496     if (n_rects > 0 && rects == nullptr)
3497     {
3498         return EglBadParameter() << "n_rects cannot be greater than zero when rects is NULL.";
3499     }
3500 
3501     // TODO(jmadill): Validate Surface is bound to the thread.
3502 
3503     return NoError();
3504 }
3505 
ValidateWaitNative(const Display * display,const EGLint engine)3506 Error ValidateWaitNative(const Display *display, const EGLint engine)
3507 {
3508     ANGLE_TRY(ValidateDisplay(display));
3509 
3510     if (engine != EGL_CORE_NATIVE_ENGINE)
3511     {
3512         return EglBadParameter() << "the 'engine' parameter has an unrecognized value";
3513     }
3514 
3515     return NoError();
3516 }
3517 
ValidateCopyBuffers(Display * display,const Surface * surface)3518 Error ValidateCopyBuffers(Display *display, const Surface *surface)
3519 {
3520     ANGLE_TRY(ValidateSurface(display, surface));
3521 
3522     if (display->testDeviceLost())
3523     {
3524         return EglContextLost();
3525     }
3526 
3527     return NoError();
3528 }
3529 
3530 // Validate state for eglBindTexImage. If context is non-null then textureObject will be set to
3531 // surface's texture that will have an image bound to it
ValidateBindTexImage(const Display * display,const Surface * surface,const EGLSurface eglSurface,const EGLint buffer,const gl::Context * context,gl::Texture ** textureObject)3532 Error ValidateBindTexImage(const Display *display,
3533                            const Surface *surface,
3534                            const EGLSurface eglSurface,
3535                            const EGLint buffer,
3536                            const gl::Context *context,
3537                            gl::Texture **textureObject)
3538 {
3539     ANGLE_TRY(ValidateSurface(display, surface));
3540 
3541     if (buffer != EGL_BACK_BUFFER)
3542     {
3543         return EglBadParameter();
3544     }
3545 
3546     if (eglSurface == EGL_NO_SURFACE || surface->getType() == EGL_WINDOW_BIT)
3547     {
3548         return EglBadSurface();
3549     }
3550 
3551     if (surface->getBoundTexture())
3552     {
3553         return EglBadAccess();
3554     }
3555 
3556     if (surface->getTextureFormat() == TextureFormat::NoTexture)
3557     {
3558         return EglBadMatch();
3559     }
3560 
3561     if (context)
3562     {
3563         gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
3564         *textureObject       = context->getTextureByType(type);
3565         ASSERT(*textureObject != nullptr);
3566 
3567         if ((*textureObject)->getImmutableFormat())
3568         {
3569             return EglBadMatch();
3570         }
3571     }
3572 
3573     return NoError();
3574 }
3575 
ValidateReleaseTexImage(const Display * display,const Surface * surface,const EGLSurface eglSurface,const EGLint buffer)3576 Error ValidateReleaseTexImage(const Display *display,
3577                               const Surface *surface,
3578                               const EGLSurface eglSurface,
3579                               const EGLint buffer)
3580 {
3581     ANGLE_TRY(ValidateSurface(display, surface));
3582 
3583     if (buffer != EGL_BACK_BUFFER)
3584     {
3585         return EglBadParameter();
3586     }
3587 
3588     if (eglSurface == EGL_NO_SURFACE || surface->getType() == EGL_WINDOW_BIT)
3589     {
3590         return EglBadSurface();
3591     }
3592 
3593     if (surface->getTextureFormat() == TextureFormat::NoTexture)
3594     {
3595         return EglBadMatch();
3596     }
3597 
3598     return NoError();
3599 }
3600 
ValidateSwapInterval(const Display * display,const Surface * draw_surface,const gl::Context * context)3601 Error ValidateSwapInterval(const Display *display,
3602                            const Surface *draw_surface,
3603                            const gl::Context *context)
3604 {
3605     ANGLE_TRY(ValidateContext(display, context));
3606 
3607     if (draw_surface == nullptr)
3608     {
3609         return EglBadSurface();
3610     }
3611 
3612     return NoError();
3613 }
3614 
ValidateBindAPI(const EGLenum api)3615 Error ValidateBindAPI(const EGLenum api)
3616 {
3617     switch (api)
3618     {
3619         case EGL_OPENGL_API:
3620         case EGL_OPENVG_API:
3621             return EglBadParameter();  // Not supported by this implementation
3622         case EGL_OPENGL_ES_API:
3623             break;
3624         default:
3625             return EglBadParameter();
3626     }
3627 
3628     return NoError();
3629 }
3630 
ValidatePresentationTimeANDROID(const Display * display,const Surface * surface,EGLnsecsANDROID time)3631 Error ValidatePresentationTimeANDROID(const Display *display,
3632                                       const Surface *surface,
3633                                       EGLnsecsANDROID time)
3634 {
3635     ANGLE_TRY(ValidateDisplay(display));
3636 
3637     if (!display->getExtensions().presentationTime)
3638     {
3639         // It is out of spec what happens when calling an extension function when the extension is
3640         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
3641         return EglBadDisplay() << "EGL_ANDROID_presentation_time is not available.";
3642     }
3643 
3644     ANGLE_TRY(ValidateSurface(display, surface));
3645 
3646     return NoError();
3647 }
3648 
ValidateSetBlobCacheANDROID(const Display * display,EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)3649 Error ValidateSetBlobCacheANDROID(const Display *display,
3650                                   EGLSetBlobFuncANDROID set,
3651                                   EGLGetBlobFuncANDROID get)
3652 {
3653     ANGLE_TRY(ValidateDisplay(display));
3654 
3655     if (display->areBlobCacheFuncsSet())
3656     {
3657         return EglBadParameter()
3658                << "Blob cache functions can only be set once in the lifetime of a Display";
3659     }
3660 
3661     if (set == nullptr || get == nullptr)
3662     {
3663         return EglBadParameter() << "Blob cache callbacks cannot be null.";
3664     }
3665 
3666     return NoError();
3667 }
3668 
ValidateGetConfigAttrib(const Display * display,const Config * config,EGLint attribute)3669 Error ValidateGetConfigAttrib(const Display *display, const Config *config, EGLint attribute)
3670 {
3671     ANGLE_TRY(ValidateConfig(display, config));
3672     ANGLE_TRY(ValidateConfigAttribute(display, static_cast<EGLAttrib>(attribute)));
3673     return NoError();
3674 }
3675 
ValidateChooseConfig(const Display * display,const AttributeMap & attribs,EGLint configSize,EGLint * numConfig)3676 Error ValidateChooseConfig(const Display *display,
3677                            const AttributeMap &attribs,
3678                            EGLint configSize,
3679                            EGLint *numConfig)
3680 {
3681     ANGLE_TRY(ValidateDisplay(display));
3682     ANGLE_TRY(ValidateConfigAttributes(display, attribs));
3683 
3684     if (numConfig == nullptr)
3685     {
3686         return EglBadParameter() << "num_config cannot be null.";
3687     }
3688 
3689     return NoError();
3690 }
3691 
ValidateGetConfigs(const Display * display,EGLint configSize,EGLint * numConfig)3692 Error ValidateGetConfigs(const Display *display, EGLint configSize, EGLint *numConfig)
3693 {
3694     ANGLE_TRY(ValidateDisplay(display));
3695 
3696     if (numConfig == nullptr)
3697     {
3698         return EglBadParameter() << "num_config cannot be null.";
3699     }
3700 
3701     return NoError();
3702 }
3703 
ValidateGetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)3704 Error ValidateGetPlatformDisplay(EGLenum platform,
3705                                  void *native_display,
3706                                  const EGLAttrib *attrib_list)
3707 {
3708     const auto &attribMap = AttributeMap::CreateFromAttribArray(attrib_list);
3709     return ValidateGetPlatformDisplayCommon(platform, native_display, attribMap);
3710 }
3711 
ValidateGetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)3712 Error ValidateGetPlatformDisplayEXT(EGLenum platform,
3713                                     void *native_display,
3714                                     const EGLint *attrib_list)
3715 {
3716     const auto &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
3717     return ValidateGetPlatformDisplayCommon(platform, native_display, attribMap);
3718 }
3719 
ValidateCreatePlatformWindowSurfaceEXT(const Display * display,const Config * configuration,void * nativeWindow,const AttributeMap & attributes)3720 Error ValidateCreatePlatformWindowSurfaceEXT(const Display *display,
3721                                              const Config *configuration,
3722                                              void *nativeWindow,
3723                                              const AttributeMap &attributes)
3724 {
3725     if (!Display::GetClientExtensions().platformBase)
3726     {
3727         return EglBadAccess() << "EGL_EXT_platform_base not supported";
3728     }
3729 
3730     ANGLE_TRY(ValidateConfig(display, configuration));
3731 
3732     return EglBadDisplay() << "ValidateCreatePlatformWindowSurfaceEXT unimplemented.";
3733 }
3734 
ValidateCreatePlatformPixmapSurfaceEXT(const Display * display,const Config * configuration,void * nativePixmap,const AttributeMap & attributes)3735 Error ValidateCreatePlatformPixmapSurfaceEXT(const Display *display,
3736                                              const Config *configuration,
3737                                              void *nativePixmap,
3738                                              const AttributeMap &attributes)
3739 {
3740     if (!Display::GetClientExtensions().platformBase)
3741     {
3742         return EglBadAccess() << "EGL_EXT_platform_base not supported";
3743     }
3744 
3745     ANGLE_TRY(ValidateConfig(display, configuration));
3746 
3747     return EglBadDisplay() << "ValidateCreatePlatformPixmapSurfaceEXT unimplemented.";
3748 }
3749 
ValidateProgramCacheGetAttribANGLE(const Display * display,EGLenum attrib)3750 Error ValidateProgramCacheGetAttribANGLE(const Display *display, EGLenum attrib)
3751 {
3752     ANGLE_TRY(ValidateDisplay(display));
3753 
3754     if (!display->getExtensions().programCacheControl)
3755     {
3756         return EglBadAccess() << "Extension not supported";
3757     }
3758 
3759     switch (attrib)
3760     {
3761         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
3762         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
3763             break;
3764 
3765         default:
3766             return EglBadParameter() << "Invalid program cache attribute.";
3767     }
3768 
3769     return NoError();
3770 }
3771 
ValidateProgramCacheQueryANGLE(const Display * display,EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)3772 Error ValidateProgramCacheQueryANGLE(const Display *display,
3773                                      EGLint index,
3774                                      void *key,
3775                                      EGLint *keysize,
3776                                      void *binary,
3777                                      EGLint *binarysize)
3778 {
3779     ANGLE_TRY(ValidateDisplay(display));
3780 
3781     if (!display->getExtensions().programCacheControl)
3782     {
3783         return EglBadAccess() << "Extension not supported";
3784     }
3785 
3786     if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
3787     {
3788         return EglBadParameter() << "Program index out of range.";
3789     }
3790 
3791     if (keysize == nullptr || binarysize == nullptr)
3792     {
3793         return EglBadParameter() << "keysize and binarysize must always be valid pointers.";
3794     }
3795 
3796     if (binary && *keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
3797     {
3798         return EglBadParameter() << "Invalid program key size.";
3799     }
3800 
3801     if ((key == nullptr) != (binary == nullptr))
3802     {
3803         return EglBadParameter() << "key and binary must both be null or both non-null.";
3804     }
3805 
3806     return NoError();
3807 }
3808 
ValidateProgramCachePopulateANGLE(const Display * display,const void * key,EGLint keysize,const void * binary,EGLint binarysize)3809 Error ValidateProgramCachePopulateANGLE(const Display *display,
3810                                         const void *key,
3811                                         EGLint keysize,
3812                                         const void *binary,
3813                                         EGLint binarysize)
3814 {
3815     ANGLE_TRY(ValidateDisplay(display));
3816 
3817     if (!display->getExtensions().programCacheControl)
3818     {
3819         return EglBadAccess() << "Extension not supported";
3820     }
3821 
3822     if (keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
3823     {
3824         return EglBadParameter() << "Invalid program key size.";
3825     }
3826 
3827     if (key == nullptr || binary == nullptr)
3828     {
3829         return EglBadParameter() << "null pointer in arguments.";
3830     }
3831 
3832     // Upper bound for binarysize is arbitrary.
3833     if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
3834     {
3835         return EglBadParameter() << "binarysize out of valid range.";
3836     }
3837 
3838     return NoError();
3839 }
3840 
ValidateProgramCacheResizeANGLE(const Display * display,EGLint limit,EGLenum mode)3841 Error ValidateProgramCacheResizeANGLE(const Display *display, EGLint limit, EGLenum mode)
3842 {
3843     ANGLE_TRY(ValidateDisplay(display));
3844 
3845     if (!display->getExtensions().programCacheControl)
3846     {
3847         return EglBadAccess() << "Extension not supported";
3848     }
3849 
3850     if (limit < 0)
3851     {
3852         return EglBadParameter() << "limit must be non-negative.";
3853     }
3854 
3855     switch (mode)
3856     {
3857         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
3858         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
3859             break;
3860 
3861         default:
3862             return EglBadParameter() << "Invalid cache resize mode.";
3863     }
3864 
3865     return NoError();
3866 }
3867 
ValidateSurfaceAttrib(const Display * display,const Surface * surface,EGLint attribute,EGLint value)3868 Error ValidateSurfaceAttrib(const Display *display,
3869                             const Surface *surface,
3870                             EGLint attribute,
3871                             EGLint value)
3872 {
3873     ANGLE_TRY(ValidateDisplay(display));
3874     ANGLE_TRY(ValidateSurface(display, surface));
3875 
3876     if (surface == EGL_NO_SURFACE)
3877     {
3878         return EglBadSurface() << "Surface cannot be EGL_NO_SURFACE.";
3879     }
3880 
3881     switch (attribute)
3882     {
3883         case EGL_MIPMAP_LEVEL:
3884             break;
3885 
3886         case EGL_MULTISAMPLE_RESOLVE:
3887             switch (value)
3888             {
3889                 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
3890                     break;
3891 
3892                 case EGL_MULTISAMPLE_RESOLVE_BOX:
3893                     if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
3894                     {
3895                         return EglBadMatch()
3896                                << "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.";
3897                     }
3898                     break;
3899 
3900                 default:
3901                     return EglBadAttribute() << "Invalid multisample resolve type.";
3902             }
3903             break;
3904 
3905         case EGL_SWAP_BEHAVIOR:
3906             switch (value)
3907             {
3908                 case EGL_BUFFER_PRESERVED:
3909                     if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
3910                     {
3911                         return EglBadMatch()
3912                                << "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.";
3913                     }
3914                     break;
3915 
3916                 case EGL_BUFFER_DESTROYED:
3917                     break;
3918 
3919                 default:
3920                     return EglBadAttribute() << "Invalid swap behaviour.";
3921             }
3922             break;
3923 
3924         case EGL_WIDTH:
3925         case EGL_HEIGHT:
3926             if (!display->getExtensions().windowFixedSize)
3927             {
3928                 return EglBadAttribute() << "EGL_WIDTH or EGL_HEIGHT cannot be set without "
3929                                             "EGL_ANGLE_window_fixed_size support.";
3930             }
3931             if (!surface->isFixedSize())
3932             {
3933                 return EglBadMatch() << "EGL_WIDTH or EGL_HEIGHT cannot be set without "
3934                                         "EGL_FIXED_SIZE_ANGLE being enabled on the surface.";
3935             }
3936             break;
3937 
3938         case EGL_TIMESTAMPS_ANDROID:
3939             if (!display->getExtensions().getFrameTimestamps)
3940             {
3941                 return EglBadAttribute() << "EGL_TIMESTAMPS_ANDROID cannot be used without "
3942                                             "EGL_ANDROID_get_frame_timestamps support.";
3943             }
3944             switch (value)
3945             {
3946                 case EGL_TRUE:
3947                 case EGL_FALSE:
3948                     break;
3949 
3950                 default:
3951                     return EglBadAttribute() << "Invalid value.";
3952             }
3953             break;
3954 
3955         default:
3956             return EglBadAttribute() << "Invalid surface attribute.";
3957     }
3958 
3959     return NoError();
3960 }
3961 
ValidateQuerySurface(const Display * display,const Surface * surface,EGLint attribute,EGLint * value)3962 Error ValidateQuerySurface(const Display *display,
3963                            const Surface *surface,
3964                            EGLint attribute,
3965                            EGLint *value)
3966 {
3967     ANGLE_TRY(ValidateDisplay(display));
3968     ANGLE_TRY(ValidateSurface(display, surface));
3969 
3970     if (surface == EGL_NO_SURFACE)
3971     {
3972         return EglBadSurface() << "Surface cannot be EGL_NO_SURFACE.";
3973     }
3974 
3975     switch (attribute)
3976     {
3977         case EGL_GL_COLORSPACE:
3978         case EGL_VG_ALPHA_FORMAT:
3979         case EGL_VG_COLORSPACE:
3980         case EGL_CONFIG_ID:
3981         case EGL_HEIGHT:
3982         case EGL_HORIZONTAL_RESOLUTION:
3983         case EGL_LARGEST_PBUFFER:
3984         case EGL_MIPMAP_TEXTURE:
3985         case EGL_MIPMAP_LEVEL:
3986         case EGL_MULTISAMPLE_RESOLVE:
3987         case EGL_PIXEL_ASPECT_RATIO:
3988         case EGL_RENDER_BUFFER:
3989         case EGL_SWAP_BEHAVIOR:
3990         case EGL_TEXTURE_FORMAT:
3991         case EGL_TEXTURE_TARGET:
3992         case EGL_VERTICAL_RESOLUTION:
3993         case EGL_WIDTH:
3994             break;
3995 
3996         case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
3997             if (!display->getExtensions().postSubBuffer)
3998             {
3999                 return EglBadAttribute() << "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
4000                                             "without EGL_ANGLE_surface_orientation support.";
4001             }
4002             break;
4003 
4004         case EGL_FIXED_SIZE_ANGLE:
4005             if (!display->getExtensions().windowFixedSize)
4006             {
4007                 return EglBadAttribute() << "EGL_FIXED_SIZE_ANGLE cannot be used without "
4008                                             "EGL_ANGLE_window_fixed_size support.";
4009             }
4010             break;
4011 
4012         case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
4013             if (!display->getExtensions().flexibleSurfaceCompatibility)
4014             {
4015                 return EglBadAttribute()
4016                        << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be "
4017                           "used without EGL_ANGLE_flexible_surface_compatibility support.";
4018             }
4019             break;
4020 
4021         case EGL_SURFACE_ORIENTATION_ANGLE:
4022             if (!display->getExtensions().surfaceOrientation)
4023             {
4024                 return EglBadAttribute() << "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
4025                                             "queried without "
4026                                             "EGL_ANGLE_surface_orientation support.";
4027             }
4028             break;
4029 
4030         case EGL_DIRECT_COMPOSITION_ANGLE:
4031             if (!display->getExtensions().directComposition)
4032             {
4033                 return EglBadAttribute() << "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
4034                                             "used without "
4035                                             "EGL_ANGLE_direct_composition support.";
4036             }
4037             break;
4038 
4039         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
4040             if (!display->getExtensions().robustResourceInitialization)
4041             {
4042                 return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
4043                                             "used without EGL_ANGLE_robust_resource_initialization "
4044                                             "support.";
4045             }
4046             break;
4047 
4048         case EGL_TIMESTAMPS_ANDROID:
4049             if (!display->getExtensions().getFrameTimestamps)
4050             {
4051                 return EglBadAttribute() << "EGL_TIMESTAMPS_ANDROID cannot be used without "
4052                                             "EGL_ANDROID_get_frame_timestamps support.";
4053             }
4054             break;
4055 
4056         default:
4057             return EglBadAttribute() << "Invalid surface attribute.";
4058     }
4059 
4060     return NoError();
4061 }
4062 
ValidateQueryContext(const Display * display,const gl::Context * context,EGLint attribute,EGLint * value)4063 Error ValidateQueryContext(const Display *display,
4064                            const gl::Context *context,
4065                            EGLint attribute,
4066                            EGLint *value)
4067 {
4068     ANGLE_TRY(ValidateContext(display, context));
4069 
4070     switch (attribute)
4071     {
4072         case EGL_CONFIG_ID:
4073         case EGL_CONTEXT_CLIENT_TYPE:
4074         case EGL_CONTEXT_CLIENT_VERSION:
4075         case EGL_RENDER_BUFFER:
4076             break;
4077 
4078         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
4079             if (!display->getExtensions().robustResourceInitialization)
4080             {
4081                 return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
4082                                             "used without EGL_ANGLE_robust_resource_initialization "
4083                                             "support.";
4084             }
4085             break;
4086 
4087         default:
4088             return EglBadAttribute() << "Invalid context attribute.";
4089     }
4090 
4091     return NoError();
4092 }
4093 
ValidateDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const AttributeMap & attribs)4094 Error ValidateDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const AttributeMap &attribs)
4095 {
4096     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
4097     if (!clientExtensions.debug)
4098     {
4099         return EglBadAccess() << "EGL_KHR_debug extension is not available.";
4100     }
4101 
4102     for (const auto &attrib : attribs)
4103     {
4104         switch (attrib.first)
4105         {
4106             case EGL_DEBUG_MSG_CRITICAL_KHR:
4107             case EGL_DEBUG_MSG_ERROR_KHR:
4108             case EGL_DEBUG_MSG_WARN_KHR:
4109             case EGL_DEBUG_MSG_INFO_KHR:
4110                 if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
4111                 {
4112                     return EglBadAttribute() << "message controls must be EGL_TRUE or EGL_FALSE.";
4113                 }
4114                 break;
4115         }
4116     }
4117 
4118     return NoError();
4119 }
4120 
ValidateQueryDebugKHR(EGLint attribute,EGLAttrib * value)4121 Error ValidateQueryDebugKHR(EGLint attribute, EGLAttrib *value)
4122 {
4123     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
4124     if (!clientExtensions.debug)
4125     {
4126         return EglBadAccess() << "EGL_KHR_debug extension is not available.";
4127     }
4128 
4129     switch (attribute)
4130     {
4131         case EGL_DEBUG_MSG_CRITICAL_KHR:
4132         case EGL_DEBUG_MSG_ERROR_KHR:
4133         case EGL_DEBUG_MSG_WARN_KHR:
4134         case EGL_DEBUG_MSG_INFO_KHR:
4135         case EGL_DEBUG_CALLBACK_KHR:
4136             break;
4137 
4138         default:
4139             return EglBadAttribute() << "unknown attribute.";
4140     }
4141 
4142     return NoError();
4143 }
4144 
ValidateLabelObjectKHR(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object,EGLLabelKHR label)4145 Error ValidateLabelObjectKHR(Thread *thread,
4146                              const Display *display,
4147                              ObjectType objectType,
4148                              EGLObjectKHR object,
4149                              EGLLabelKHR label)
4150 {
4151     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
4152     if (!clientExtensions.debug)
4153     {
4154         return EglBadAccess() << "EGL_KHR_debug extension is not available.";
4155     }
4156 
4157     LabeledObject *labeledObject = nullptr;
4158     ANGLE_TRY(ValidateLabeledObject(thread, display, objectType, object, &labeledObject));
4159 
4160     return NoError();
4161 }
4162 
ValidateGetCompositorTimingSupportedANDROID(const Display * display,const Surface * surface,CompositorTiming name)4163 Error ValidateGetCompositorTimingSupportedANDROID(const Display *display,
4164                                                   const Surface *surface,
4165                                                   CompositorTiming name)
4166 {
4167     ANGLE_TRY(ValidateDisplay(display));
4168 
4169     if (!display->getExtensions().getFrameTimestamps)
4170     {
4171         return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4172     }
4173 
4174     ANGLE_TRY(ValidateSurface(display, surface));
4175 
4176     if (!ValidCompositorTimingName(name))
4177     {
4178         return EglBadParameter() << "invalid timing name.";
4179     }
4180 
4181     return NoError();
4182 }
4183 
ValidateGetCompositorTimingANDROID(const Display * display,const Surface * surface,EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values)4184 Error ValidateGetCompositorTimingANDROID(const Display *display,
4185                                          const Surface *surface,
4186                                          EGLint numTimestamps,
4187                                          const EGLint *names,
4188                                          EGLnsecsANDROID *values)
4189 {
4190     ANGLE_TRY(ValidateDisplay(display));
4191 
4192     if (!display->getExtensions().getFrameTimestamps)
4193     {
4194         return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4195     }
4196 
4197     ANGLE_TRY(ValidateSurface(display, surface));
4198 
4199     if (names == nullptr && numTimestamps > 0)
4200     {
4201         return EglBadParameter() << "names is NULL.";
4202     }
4203 
4204     if (values == nullptr && numTimestamps > 0)
4205     {
4206         return EglBadParameter() << "values is NULL.";
4207     }
4208 
4209     if (numTimestamps < 0)
4210     {
4211         return EglBadParameter() << "numTimestamps must be at least 0.";
4212     }
4213 
4214     for (EGLint i = 0; i < numTimestamps; i++)
4215     {
4216         CompositorTiming name = FromEGLenum<CompositorTiming>(names[i]);
4217 
4218         if (!ValidCompositorTimingName(name))
4219         {
4220             return EglBadParameter() << "invalid compositor timing.";
4221         }
4222 
4223         if (!surface->getSupportedCompositorTimings().test(name))
4224         {
4225             return EglBadParameter() << "compositor timing not supported by surface.";
4226         }
4227     }
4228 
4229     return NoError();
4230 }
4231 
ValidateGetNextFrameIdANDROID(const Display * display,const Surface * surface,EGLuint64KHR * frameId)4232 Error ValidateGetNextFrameIdANDROID(const Display *display,
4233                                     const Surface *surface,
4234                                     EGLuint64KHR *frameId)
4235 {
4236     ANGLE_TRY(ValidateDisplay(display));
4237 
4238     if (!display->getExtensions().getFrameTimestamps)
4239     {
4240         return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4241     }
4242 
4243     ANGLE_TRY(ValidateSurface(display, surface));
4244 
4245     if (frameId == nullptr)
4246     {
4247         return EglBadParameter() << "frameId is NULL.";
4248     }
4249 
4250     return NoError();
4251 }
4252 
ValidateGetFrameTimestampSupportedANDROID(const Display * display,const Surface * surface,Timestamp timestamp)4253 Error ValidateGetFrameTimestampSupportedANDROID(const Display *display,
4254                                                 const Surface *surface,
4255                                                 Timestamp timestamp)
4256 {
4257     ANGLE_TRY(ValidateDisplay(display));
4258 
4259     if (!display->getExtensions().getFrameTimestamps)
4260     {
4261         return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4262     }
4263 
4264     ANGLE_TRY(ValidateSurface(display, surface));
4265 
4266     if (!ValidTimestampType(timestamp))
4267     {
4268         return EglBadParameter() << "invalid timestamp type.";
4269     }
4270 
4271     return NoError();
4272 }
4273 
ValidateGetFrameTimestampsANDROID(const Display * display,const Surface * surface,EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values)4274 Error ValidateGetFrameTimestampsANDROID(const Display *display,
4275                                         const Surface *surface,
4276                                         EGLuint64KHR frameId,
4277                                         EGLint numTimestamps,
4278                                         const EGLint *timestamps,
4279                                         EGLnsecsANDROID *values)
4280 {
4281     ANGLE_TRY(ValidateDisplay(display));
4282 
4283     if (!display->getExtensions().getFrameTimestamps)
4284     {
4285         return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4286     }
4287 
4288     ANGLE_TRY(ValidateSurface(display, surface));
4289 
4290     if (!surface->isTimestampsEnabled())
4291     {
4292         return EglBadSurface() << "timestamp collection is not enabled for this surface.";
4293     }
4294 
4295     if (timestamps == nullptr && numTimestamps > 0)
4296     {
4297         return EglBadParameter() << "timestamps is NULL.";
4298     }
4299 
4300     if (values == nullptr && numTimestamps > 0)
4301     {
4302         return EglBadParameter() << "values is NULL.";
4303     }
4304 
4305     if (numTimestamps < 0)
4306     {
4307         return EglBadParameter() << "numTimestamps must be at least 0.";
4308     }
4309 
4310     for (EGLint i = 0; i < numTimestamps; i++)
4311     {
4312         Timestamp timestamp = FromEGLenum<Timestamp>(timestamps[i]);
4313 
4314         if (!ValidTimestampType(timestamp))
4315         {
4316             return EglBadParameter() << "invalid timestamp type.";
4317         }
4318 
4319         if (!surface->getSupportedTimestamps().test(timestamp))
4320         {
4321             return EglBadParameter() << "timestamp not supported by surface.";
4322         }
4323     }
4324 
4325     return NoError();
4326 }
4327 
ValidateQueryStringiANGLE(const Display * display,EGLint name,EGLint index)4328 Error ValidateQueryStringiANGLE(const Display *display, EGLint name, EGLint index)
4329 {
4330     ANGLE_TRY(ValidateDisplay(display));
4331 
4332     if (!Display::GetClientExtensions().featureControlANGLE)
4333     {
4334         return EglBadDisplay() << "EGL_ANGLE_feature_control extension is not available.";
4335     }
4336 
4337     if (index < 0)
4338     {
4339         return EglBadParameter() << "index is negative.";
4340     }
4341 
4342     switch (name)
4343     {
4344         case EGL_FEATURE_NAME_ANGLE:
4345         case EGL_FEATURE_CATEGORY_ANGLE:
4346         case EGL_FEATURE_DESCRIPTION_ANGLE:
4347         case EGL_FEATURE_BUG_ANGLE:
4348         case EGL_FEATURE_STATUS_ANGLE:
4349         case EGL_FEATURE_CONDITION_ANGLE:
4350             break;
4351         default:
4352             return EglBadParameter() << "name is not valid.";
4353     }
4354 
4355     if (static_cast<size_t>(index) >= display->getFeatures().size())
4356     {
4357         return EglBadParameter() << "index is too big.";
4358     }
4359 
4360     return NoError();
4361 }
4362 
ValidateQueryDisplayAttribBase(const Display * display,const EGLint attribute)4363 Error ValidateQueryDisplayAttribBase(const Display *display, const EGLint attribute)
4364 {
4365     ANGLE_TRY(ValidateDisplay(display));
4366 
4367     switch (attribute)
4368     {
4369         case EGL_DEVICE_EXT:
4370             if (!display->getExtensions().deviceQuery)
4371             {
4372                 return EglBadDisplay() << "EGL_EXT_device_query extension is not available.";
4373             }
4374             break;
4375 
4376         case EGL_FEATURE_COUNT_ANGLE:
4377             if (!Display::GetClientExtensions().featureControlANGLE)
4378             {
4379                 return EglBadDisplay() << "EGL_ANGLE_feature_control extension is not available.";
4380             }
4381             break;
4382 
4383         default:
4384             return EglBadAttribute() << "attribute is not valid.";
4385     }
4386 
4387     return NoError();
4388 }
4389 
ValidateQueryDisplayAttribEXT(const Display * display,const EGLint attribute)4390 Error ValidateQueryDisplayAttribEXT(const Display *display, const EGLint attribute)
4391 {
4392     ANGLE_TRY(ValidateQueryDisplayAttribBase(display, attribute));
4393 
4394     return NoError();
4395 }
4396 
ValidateQueryDisplayAttribANGLE(const Display * display,const EGLint attribute)4397 Error ValidateQueryDisplayAttribANGLE(const Display *display, const EGLint attribute)
4398 {
4399     ANGLE_TRY(ValidateQueryDisplayAttribBase(display, attribute));
4400 
4401     return NoError();
4402 }
4403 
ValidateGetNativeClientBufferANDROID(const AHardwareBuffer * buffer)4404 Error ValidateGetNativeClientBufferANDROID(const AHardwareBuffer *buffer)
4405 {
4406     // No extension check is done because no display is passed to eglGetNativeClientBufferANDROID
4407     // despite it being a display extension.  No display is needed for the implementation though.
4408     if (buffer == nullptr)
4409     {
4410         return EglBadParameter() << "NULL buffer.";
4411     }
4412 
4413     return NoError();
4414 }
4415 
ValidateDupNativeFenceFDANDROID(const Display * display,const Sync * sync)4416 Error ValidateDupNativeFenceFDANDROID(const Display *display, const Sync *sync)
4417 {
4418     ANGLE_TRY(ValidateDisplay(display));
4419 
4420     if (!display->getExtensions().nativeFenceSyncANDROID)
4421     {
4422         return EglBadDisplay() << "EGL_ANDROID_native_fence_sync extension is not available.";
4423     }
4424 
4425     ANGLE_TRY(ValidateSync(display, sync));
4426 
4427     return NoError();
4428 }
4429 
ValidateSwapBuffersWithFrameTokenANGLE(const Display * display,const Surface * surface,EGLFrameTokenANGLE frametoken)4430 Error ValidateSwapBuffersWithFrameTokenANGLE(const Display *display,
4431                                              const Surface *surface,
4432                                              EGLFrameTokenANGLE frametoken)
4433 {
4434     ANGLE_TRY(ValidateDisplay(display));
4435 
4436     if (!display->getExtensions().swapWithFrameToken)
4437     {
4438         return EglBadDisplay() << "EGL_ANGLE_swap_buffers_with_frame_token is not available.";
4439     }
4440 
4441     ANGLE_TRY(ValidateSurface(display, surface));
4442 
4443     return NoError();
4444 }
4445 }  // namespace egl
4446