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