1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #ifndef GLLIBRARYEGL_H_
6 #define GLLIBRARYEGL_H_
7 
8 #if defined(MOZ_X11)
9 #  include "mozilla/X11Util.h"
10 #endif
11 
12 #include "GLTypes.h"
13 #include "mozilla/EnumTypeTraits.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/RefPtr.h"
16 #include "nsISupports.h"
17 #include "prlink.h"
18 
19 #include <bitset>
20 #include <memory>
21 #include <unordered_map>
22 
23 #ifdef MOZ_WIDGET_ANDROID
24 #  include "mozilla/ProfilerLabels.h"
25 #endif
26 
27 #if defined(MOZ_X11)
28 #  define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
29 #else
30 #  define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
31 #endif
32 
33 struct ID3D11Device;
34 
35 extern "C" {
36 struct AHardwareBuffer;
37 }
38 
39 namespace angle {
40 class Platform;
41 }
42 
43 namespace mozilla {
44 
45 namespace gfx {
46 class DataSourceSurface;
47 }
48 
49 namespace gl {
50 
51 class SymbolLoader;
52 
53 PRLibrary* LoadApitraceLibrary();
54 
55 void BeforeEGLCall(const char* funcName);
56 void AfterEGLCall(const char* funcName);
57 
58 class EglDisplay;
59 /**
60  * Known GL extensions that can be queried by
61  * IsExtensionSupported.  The results of this are cached, and as
62  * such it's safe to use this even in performance critical code.
63  * If you add to this array, remember to add to the string names
64  * in GLLibraryEGL.cpp.
65  */
66 enum class EGLLibExtension {
67   ANDROID_get_native_client_buffer,
68   ANGLE_device_creation,
69   ANGLE_device_creation_d3d11,
70   ANGLE_platform_angle,
71   ANGLE_platform_angle_d3d,
72   EXT_device_query,
73   Max
74 };
75 
76 /**
77  * Known GL extensions that can be queried by
78  * IsExtensionSupported.  The results of this are cached, and as
79  * such it's safe to use this even in performance critical code.
80  * If you add to this array, remember to add to the string names
81  * in GLLibraryEGL.cpp.
82  */
83 enum class EGLExtension {
84   KHR_image_base,
85   KHR_image_pixmap,
86   KHR_gl_texture_2D_image,
87   ANGLE_surface_d3d_texture_2d_share_handle,
88   EXT_create_context_robustness,
89   KHR_image,
90   KHR_fence_sync,
91   KHR_wait_sync,
92   ANDROID_native_fence_sync,
93   EGL_ANDROID_image_crop,
94   ANGLE_d3d_share_handle_client_buffer,
95   KHR_create_context,
96   KHR_stream,
97   KHR_stream_consumer_gltexture,
98   NV_stream_consumer_gltexture_yuv,
99   ANGLE_stream_producer_d3d_texture,
100   KHR_surfaceless_context,
101   KHR_create_context_no_error,
102   MOZ_create_context_provoking_vertex_dont_care,
103   EXT_swap_buffers_with_damage,
104   KHR_swap_buffers_with_damage,
105   EXT_buffer_age,
106   KHR_partial_update,
107   NV_robustness_video_memory_purge,
108   Max
109 };
110 
111 // -
112 
113 class GLLibraryEGL final {
114   friend class EglDisplay;
115 
116  public:
117   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL)
118 
119  private:
120   PRLibrary* mEGLLibrary = nullptr;
121   PRLibrary* mGLLibrary = nullptr;
122   bool mIsANGLE = false;
123   std::bitset<UnderlyingValue(EGLLibExtension::Max)> mAvailableExtensions;
124   std::weak_ptr<EglDisplay> mDefaultDisplay;
125   std::unordered_map<EGLDisplay, std::weak_ptr<EglDisplay>> mActiveDisplays;
126 
127  public:
128   static RefPtr<GLLibraryEGL> Create(nsACString* const out_failureId);
129 
130  private:
131   ~GLLibraryEGL() = default;
132 
133   bool Init(nsACString* const out_failureId);
134   void InitLibExtensions();
135 
136  public:
137   Maybe<SymbolLoader> GetSymbolLoader() const;
138 
139   std::shared_ptr<EglDisplay> CreateDisplay(bool forceAccel,
140                                             nsACString* const out_failureId);
141   std::shared_ptr<EglDisplay> CreateDisplay(ID3D11Device*);
142   std::shared_ptr<EglDisplay> DefaultDisplay(nsACString* const out_failureId);
143 
IsExtensionSupported(EGLLibExtension aKnownExtension)144   bool IsExtensionSupported(EGLLibExtension aKnownExtension) const {
145     return mAvailableExtensions[UnderlyingValue(aKnownExtension)];
146   }
147 
MarkExtensionUnsupported(EGLLibExtension aKnownExtension)148   void MarkExtensionUnsupported(EGLLibExtension aKnownExtension) {
149     mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false;
150   }
151 
IsANGLE()152   bool IsANGLE() const { return mIsANGLE; }
153 
154   // -
155   // PFN wrappers
156 
157 #ifdef MOZ_WIDGET_ANDROID
158 #  define PROFILE_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
159 #else
160 #  define PROFILE_CALL
161 #endif
162 
163 #ifndef MOZ_FUNCTION_NAME
164 #  ifdef __GNUC__
165 #    define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
166 #  elif defined(_MSC_VER)
167 #    define MOZ_FUNCTION_NAME __FUNCTION__
168 #  else
169 #    define MOZ_FUNCTION_NAME \
170       __func__  // defined in C99, supported in various C++ compilers. Just raw
171                 // function name.
172 #  endif
173 #endif
174 
175 #ifdef DEBUG
176 #  define BEFORE_CALL BeforeEGLCall(MOZ_FUNCTION_NAME);
177 #  define AFTER_CALL AfterEGLCall(MOZ_FUNCTION_NAME);
178 #else
179 #  define BEFORE_CALL
180 #  define AFTER_CALL
181 #endif
182 
183 #define WRAP(X)                \
184   PROFILE_CALL                 \
185   BEFORE_CALL                  \
186   const auto ret = mSymbols.X; \
187   AFTER_CALL                   \
188   return ret
189 
190  public:
fGetDisplay(void * display_id)191   EGLDisplay fGetDisplay(void* display_id) const {
192     WRAP(fGetDisplay(display_id));
193   }
194 
fGetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)195   EGLDisplay fGetPlatformDisplay(EGLenum platform, void* native_display,
196                                  const EGLAttrib* attrib_list) const {
197     WRAP(fGetPlatformDisplay(platform, native_display, attrib_list));
198   }
199 
fGetCurrentSurface(EGLint id)200   EGLSurface fGetCurrentSurface(EGLint id) const {
201     WRAP(fGetCurrentSurface(id));
202   }
203 
fGetCurrentContext()204   EGLContext fGetCurrentContext() const { WRAP(fGetCurrentContext()); }
205 
fBindAPI(EGLenum api)206   EGLBoolean fBindAPI(EGLenum api) const { WRAP(fBindAPI(api)); }
207 
fGetError()208   EGLint fGetError() const { WRAP(fGetError()); }
209 
fWaitNative(EGLint engine)210   EGLBoolean fWaitNative(EGLint engine) const { WRAP(fWaitNative(engine)); }
211 
fGetProcAddress(const char * procname)212   EGLCastToRelevantPtr fGetProcAddress(const char* procname) const {
213     WRAP(fGetProcAddress(procname));
214   }
215 
216   // ANGLE_device_creation
fCreateDeviceANGLE(EGLint device_type,void * native_device,const EGLAttrib * attrib_list)217   EGLDeviceEXT fCreateDeviceANGLE(EGLint device_type, void* native_device,
218                                   const EGLAttrib* attrib_list) const {
219     WRAP(fCreateDeviceANGLE(device_type, native_device, attrib_list));
220   }
221 
fReleaseDeviceANGLE(EGLDeviceEXT device)222   EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device) {
223     WRAP(fReleaseDeviceANGLE(device));
224   }
225 
226   // ANDROID_get_native_client_buffer
fGetNativeClientBufferANDROID(const struct AHardwareBuffer * buffer)227   EGLClientBuffer fGetNativeClientBufferANDROID(
228       const struct AHardwareBuffer* buffer) {
229     WRAP(fGetNativeClientBufferANDROID(buffer));
230   }
231 
232  private:
fTerminate(EGLDisplay display)233   EGLBoolean fTerminate(EGLDisplay display) const { WRAP(fTerminate(display)); }
234 
fMakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)235   EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
236                           EGLContext ctx) const {
237     WRAP(fMakeCurrent(dpy, draw, read, ctx));
238   }
239 
fDestroyContext(EGLDisplay dpy,EGLContext ctx)240   EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const {
241     WRAP(fDestroyContext(dpy, ctx));
242   }
243 
fCreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)244   EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config,
245                             EGLContext share_context,
246                             const EGLint* attrib_list) const {
247     WRAP(fCreateContext(dpy, config, share_context, attrib_list));
248   }
249 
fDestroySurface(EGLDisplay dpy,EGLSurface surface)250   EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const {
251     WRAP(fDestroySurface(dpy, surface));
252   }
253 
254  public:
fCreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)255   EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
256                                   EGLNativeWindowType win,
257                                   const EGLint* attrib_list) const {
258     WRAP(fCreateWindowSurface(dpy, config, win, attrib_list));
259   }
260 
261  private:
fCreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)262   EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
263                                    const EGLint* attrib_list) const {
264     WRAP(fCreatePbufferSurface(dpy, config, attrib_list));
265   }
266 
fCreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)267   EGLSurface fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
268                                             EGLClientBuffer buffer,
269                                             EGLConfig config,
270                                             const EGLint* attrib_list) const {
271     WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
272                                         attrib_list));
273   }
274 
fCreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)275   EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
276                                   EGLNativePixmapType pixmap,
277                                   const EGLint* attrib_list) const {
278     WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list));
279   }
280 
fInitialize(EGLDisplay dpy,EGLint * major,EGLint * minor)281   EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const {
282     WRAP(fInitialize(dpy, major, minor));
283   }
284 
fChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)285   EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list,
286                            EGLConfig* configs, EGLint config_size,
287                            EGLint* num_config) const {
288     WRAP(fChooseConfig(dpy, attrib_list, configs, config_size, num_config));
289   }
290 
fGetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)291   EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
292                               EGLint attribute, EGLint* value) const {
293     WRAP(fGetConfigAttrib(dpy, config, attribute, value));
294   }
295 
fGetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)296   EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size,
297                          EGLint* num_config) const {
298     WRAP(fGetConfigs(dpy, configs, config_size, num_config));
299   }
300 
fSwapBuffers(EGLDisplay dpy,EGLSurface surface)301   EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const {
302     WRAP(fSwapBuffers(dpy, surface));
303   }
304 
fCopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)305   EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface,
306                           EGLNativePixmapType target) const {
307     WRAP(fCopyBuffers(dpy, surface, target));
308   }
309 
310  public:
fQueryString(EGLDisplay dpy,EGLint name)311   const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const {
312     WRAP(fQueryString(dpy, name));
313   }
314 
315  private:
fQueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)316   EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
317                            EGLint* value) const {
318     WRAP(fQueryContext(dpy, ctx, attribute, value));
319   }
320 
fBindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)321   EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface,
322                            EGLint buffer) const {
323     WRAP(fBindTexImage(dpy, surface, buffer));
324   }
325 
fReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)326   EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface,
327                               EGLint buffer) const {
328     WRAP(fReleaseTexImage(dpy, surface, buffer));
329   }
330 
fSwapInterval(EGLDisplay dpy,EGLint interval)331   EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const {
332     WRAP(fSwapInterval(dpy, interval));
333   }
334 
fCreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)335   EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
336                         EGLClientBuffer buffer,
337                         const EGLint* attrib_list) const {
338     WRAP(fCreateImageKHR(dpy, ctx, target, buffer, attrib_list));
339   }
340 
fDestroyImage(EGLDisplay dpy,EGLImage image)341   EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const {
342     WRAP(fDestroyImageKHR(dpy, image));
343   }
344 
fQuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)345   EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
346                            EGLint* value) const {
347     WRAP(fQuerySurface(dpy, surface, attribute, value));
348   }
349 
fQuerySurfacePointerANGLE(EGLDisplay dpy,EGLSurface surface,EGLint attribute,void ** value)350   EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface,
351                                        EGLint attribute, void** value) const {
352     WRAP(fQuerySurfacePointerANGLE(dpy, surface, attribute, value));
353   }
354 
fCreateSync(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)355   EGLSync fCreateSync(EGLDisplay dpy, EGLenum type,
356                       const EGLint* attrib_list) const {
357     WRAP(fCreateSyncKHR(dpy, type, attrib_list));
358   }
359 
fDestroySync(EGLDisplay dpy,EGLSync sync)360   EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) const {
361     WRAP(fDestroySyncKHR(dpy, sync));
362   }
363 
fClientWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTime timeout)364   EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags,
365                          EGLTime timeout) const {
366     WRAP(fClientWaitSyncKHR(dpy, sync, flags, timeout));
367   }
368 
fGetSyncAttrib(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLint * value)369   EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute,
370                             EGLint* value) const {
371     WRAP(fGetSyncAttribKHR(dpy, sync, attribute, value));
372   }
373 
fWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags)374   EGLint fWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) const {
375     WRAP(fWaitSyncKHR(dpy, sync, flags));
376   }
377 
fDupNativeFenceFDANDROID(EGLDisplay dpy,EGLSync sync)378   EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) const {
379     WRAP(fDupNativeFenceFDANDROID(dpy, sync));
380   }
381 
382   // KHR_stream
fCreateStreamKHR(EGLDisplay dpy,const EGLint * attrib_list)383   EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy,
384                                 const EGLint* attrib_list) const {
385     WRAP(fCreateStreamKHR(dpy, attrib_list));
386   }
387 
fDestroyStreamKHR(EGLDisplay dpy,EGLStreamKHR stream)388   EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const {
389     WRAP(fDestroyStreamKHR(dpy, stream));
390   }
391 
fQueryStreamKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint * value)392   EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
393                              EGLenum attribute, EGLint* value) const {
394     WRAP(fQueryStreamKHR(dpy, stream, attribute, value));
395   }
396 
397   // KHR_stream_consumer_gltexture
fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,EGLStreamKHR stream)398   EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
399                                                  EGLStreamKHR stream) const {
400     WRAP(fStreamConsumerGLTextureExternalKHR(dpy, stream));
401   }
402 
fStreamConsumerAcquireKHR(EGLDisplay dpy,EGLStreamKHR stream)403   EGLBoolean fStreamConsumerAcquireKHR(EGLDisplay dpy,
404                                        EGLStreamKHR stream) const {
405     WRAP(fStreamConsumerAcquireKHR(dpy, stream));
406   }
407 
fStreamConsumerReleaseKHR(EGLDisplay dpy,EGLStreamKHR stream)408   EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy,
409                                        EGLStreamKHR stream) const {
410     WRAP(fStreamConsumerReleaseKHR(dpy, stream));
411   }
412 
413   // EXT_device_query
fQueryDisplayAttribEXT(EGLDisplay dpy,EGLint attribute,EGLAttrib * value)414   EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute,
415                                     EGLAttrib* value) const {
416     WRAP(fQueryDisplayAttribEXT(dpy, attribute, value));
417   }
418 
419  public:
fQueryDeviceAttribEXT(EGLDeviceEXT device,EGLint attribute,EGLAttrib * value)420   EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute,
421                                    EGLAttrib* value) const {
422     WRAP(fQueryDeviceAttribEXT(device, attribute, value));
423   }
424 
425  private:
426   // NV_stream_consumer_gltexture_yuv
fStreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)427   EGLBoolean fStreamConsumerGLTextureExternalAttribsNV(
428       EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
429     WRAP(fStreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list));
430   }
431 
432   // ANGLE_stream_producer_d3d_texture
fCreateStreamProducerD3DTextureANGLE(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)433   EGLBoolean fCreateStreamProducerD3DTextureANGLE(
434       EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
435     WRAP(fCreateStreamProducerD3DTextureANGLE(dpy, stream, attrib_list));
436   }
437 
fStreamPostD3DTextureANGLE(EGLDisplay dpy,EGLStreamKHR stream,void * texture,const EGLAttrib * attrib_list)438   EGLBoolean fStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream,
439                                         void* texture,
440                                         const EGLAttrib* attrib_list) const {
441     WRAP(fStreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list));
442   }
443 
444   // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
fSwapBuffersWithDamage(EGLDisplay dpy,EGLSurface surface,const EGLint * rects,EGLint n_rects)445   EGLBoolean fSwapBuffersWithDamage(EGLDisplay dpy, EGLSurface surface,
446                                     const EGLint* rects, EGLint n_rects) {
447     WRAP(fSwapBuffersWithDamage(dpy, surface, rects, n_rects));
448   }
449 
450   // EGL_KHR_partial_update
fSetDamageRegion(EGLDisplay dpy,EGLSurface surface,const EGLint * rects,EGLint n_rects)451   EGLBoolean fSetDamageRegion(EGLDisplay dpy, EGLSurface surface,
452                               const EGLint* rects, EGLint n_rects) {
453     WRAP(fSetDamageRegion(dpy, surface, rects, n_rects));
454   }
455 
456 #undef WRAP
457 #undef PROFILE_CALL
458 #undef BEFORE_CALL
459 #undef AFTER_CALL
460 #undef MOZ_FUNCTION_NAME
461 
462   ////
463 
464  private:
465   struct {
466     EGLCastToRelevantPtr(GLAPIENTRY* fGetProcAddress)(const char* procname);
467     EGLDisplay(GLAPIENTRY* fGetDisplay)(void* display_id);
468     EGLDisplay(GLAPIENTRY* fGetPlatformDisplay)(EGLenum platform,
469                                                 void* native_display,
470                                                 const EGLAttrib* attrib_list);
471     EGLBoolean(GLAPIENTRY* fTerminate)(EGLDisplay dpy);
472     EGLSurface(GLAPIENTRY* fGetCurrentSurface)(EGLint);
473     EGLContext(GLAPIENTRY* fGetCurrentContext)(void);
474     EGLBoolean(GLAPIENTRY* fMakeCurrent)(EGLDisplay dpy, EGLSurface draw,
475                                          EGLSurface read, EGLContext ctx);
476     EGLBoolean(GLAPIENTRY* fDestroyContext)(EGLDisplay dpy, EGLContext ctx);
477     EGLContext(GLAPIENTRY* fCreateContext)(EGLDisplay dpy, EGLConfig config,
478                                            EGLContext share_context,
479                                            const EGLint* attrib_list);
480     EGLBoolean(GLAPIENTRY* fDestroySurface)(EGLDisplay dpy, EGLSurface surface);
481     EGLSurface(GLAPIENTRY* fCreateWindowSurface)(EGLDisplay dpy,
482                                                  EGLConfig config,
483                                                  EGLNativeWindowType win,
484                                                  const EGLint* attrib_list);
485     EGLSurface(GLAPIENTRY* fCreatePbufferSurface)(EGLDisplay dpy,
486                                                   EGLConfig config,
487                                                   const EGLint* attrib_list);
488     EGLSurface(GLAPIENTRY* fCreatePbufferFromClientBuffer)(
489         EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
490         EGLConfig config, const EGLint* attrib_list);
491     EGLSurface(GLAPIENTRY* fCreatePixmapSurface)(EGLDisplay dpy,
492                                                  EGLConfig config,
493                                                  EGLNativePixmapType pixmap,
494                                                  const EGLint* attrib_list);
495     EGLBoolean(GLAPIENTRY* fBindAPI)(EGLenum api);
496     EGLBoolean(GLAPIENTRY* fInitialize)(EGLDisplay dpy, EGLint* major,
497                                         EGLint* minor);
498     EGLBoolean(GLAPIENTRY* fChooseConfig)(EGLDisplay dpy,
499                                           const EGLint* attrib_list,
500                                           EGLConfig* configs,
501                                           EGLint config_size,
502                                           EGLint* num_config);
503     EGLint(GLAPIENTRY* fGetError)(void);
504     EGLBoolean(GLAPIENTRY* fGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
505                                              EGLint attribute, EGLint* value);
506     EGLBoolean(GLAPIENTRY* fGetConfigs)(EGLDisplay dpy, EGLConfig* configs,
507                                         EGLint config_size, EGLint* num_config);
508     EGLBoolean(GLAPIENTRY* fWaitNative)(EGLint engine);
509     EGLBoolean(GLAPIENTRY* fSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
510     EGLBoolean(GLAPIENTRY* fCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
511                                          EGLNativePixmapType target);
512     const GLubyte*(GLAPIENTRY* fQueryString)(EGLDisplay, EGLint name);
513     EGLBoolean(GLAPIENTRY* fQueryContext)(EGLDisplay dpy, EGLContext ctx,
514                                           EGLint attribute, EGLint* value);
515     EGLBoolean(GLAPIENTRY* fBindTexImage)(EGLDisplay, EGLSurface surface,
516                                           EGLint buffer);
517     EGLBoolean(GLAPIENTRY* fReleaseTexImage)(EGLDisplay, EGLSurface surface,
518                                              EGLint buffer);
519     EGLBoolean(GLAPIENTRY* fSwapInterval)(EGLDisplay dpy, EGLint interval);
520     EGLImage(GLAPIENTRY* fCreateImageKHR)(EGLDisplay dpy, EGLContext ctx,
521                                           EGLenum target,
522                                           EGLClientBuffer buffer,
523                                           const EGLint* attrib_list);
524     EGLBoolean(GLAPIENTRY* fDestroyImageKHR)(EGLDisplay dpy, EGLImage image);
525     EGLBoolean(GLAPIENTRY* fQuerySurface)(EGLDisplay dpy, EGLSurface surface,
526                                           EGLint attribute, EGLint* value);
527     EGLBoolean(GLAPIENTRY* fQuerySurfacePointerANGLE)(EGLDisplay dpy,
528                                                       EGLSurface surface,
529                                                       EGLint attribute,
530                                                       void** value);
531     EGLSync(GLAPIENTRY* fCreateSyncKHR)(EGLDisplay dpy, EGLenum type,
532                                         const EGLint* attrib_list);
533     EGLBoolean(GLAPIENTRY* fDestroySyncKHR)(EGLDisplay dpy, EGLSync sync);
534     EGLint(GLAPIENTRY* fClientWaitSyncKHR)(EGLDisplay dpy, EGLSync sync,
535                                            EGLint flags, EGLTime timeout);
536     EGLBoolean(GLAPIENTRY* fGetSyncAttribKHR)(EGLDisplay dpy, EGLSync sync,
537                                               EGLint attribute, EGLint* value);
538     EGLint(GLAPIENTRY* fWaitSyncKHR)(EGLDisplay dpy, EGLSync sync,
539                                      EGLint flags);
540     EGLint(GLAPIENTRY* fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
541     // KHR_stream
542     EGLStreamKHR(GLAPIENTRY* fCreateStreamKHR)(EGLDisplay dpy,
543                                                const EGLint* attrib_list);
544     EGLBoolean(GLAPIENTRY* fDestroyStreamKHR)(EGLDisplay dpy,
545                                               EGLStreamKHR stream);
546     EGLBoolean(GLAPIENTRY* fQueryStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream,
547                                             EGLenum attribute, EGLint* value);
548     // KHR_stream_consumer_gltexture
549     EGLBoolean(GLAPIENTRY* fStreamConsumerGLTextureExternalKHR)(
550         EGLDisplay dpy, EGLStreamKHR stream);
551     EGLBoolean(GLAPIENTRY* fStreamConsumerAcquireKHR)(EGLDisplay dpy,
552                                                       EGLStreamKHR stream);
553     EGLBoolean(GLAPIENTRY* fStreamConsumerReleaseKHR)(EGLDisplay dpy,
554                                                       EGLStreamKHR stream);
555     // EXT_device_query
556     EGLBoolean(GLAPIENTRY* fQueryDisplayAttribEXT)(EGLDisplay dpy,
557                                                    EGLint attribute,
558                                                    EGLAttrib* value);
559     EGLBoolean(GLAPIENTRY* fQueryDeviceAttribEXT)(EGLDeviceEXT device,
560                                                   EGLint attribute,
561                                                   EGLAttrib* value);
562     // NV_stream_consumer_gltexture_yuv
563     EGLBoolean(GLAPIENTRY* fStreamConsumerGLTextureExternalAttribsNV)(
564         EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list);
565     // ANGLE_stream_producer_d3d_texture
566     EGLBoolean(GLAPIENTRY* fCreateStreamProducerD3DTextureANGLE)(
567         EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list);
568     EGLBoolean(GLAPIENTRY* fStreamPostD3DTextureANGLE)(
569         EGLDisplay dpy, EGLStreamKHR stream, void* texture,
570         const EGLAttrib* attrib_list);
571     // ANGLE_device_creation
572     EGLDeviceEXT(GLAPIENTRY* fCreateDeviceANGLE)(EGLint device_type,
573                                                  void* native_device,
574                                                  const EGLAttrib* attrib_list);
575     EGLBoolean(GLAPIENTRY* fReleaseDeviceANGLE)(EGLDeviceEXT device);
576     // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
577     EGLBoolean(GLAPIENTRY* fSwapBuffersWithDamage)(EGLDisplay dpy,
578                                                    EGLSurface surface,
579                                                    const EGLint* rects,
580                                                    EGLint n_rects);
581     // EGL_KHR_partial_update
582     EGLBoolean(GLAPIENTRY* fSetDamageRegion)(EGLDisplay dpy, EGLSurface surface,
583                                              const EGLint* rects,
584                                              EGLint n_rects);
585     EGLClientBuffer(GLAPIENTRY* fGetNativeClientBufferANDROID)(
586         const struct AHardwareBuffer* buffer);
587   } mSymbols = {};
588 };
589 
590 class EglDisplay final {
591  public:
592   const RefPtr<GLLibraryEGL> mLib;
593   const EGLDisplay mDisplay;
594   const bool mIsWARP;
595 
596  private:
597   std::bitset<UnderlyingValue(EGLExtension::Max)> mAvailableExtensions;
598 
599   struct PrivateUseOnly final {};
600 
601  public:
602   static std::shared_ptr<EglDisplay> Create(GLLibraryEGL&, EGLDisplay,
603                                             bool isWarp);
604 
605   // Only `public` for make_shared.
606   EglDisplay(const PrivateUseOnly&, GLLibraryEGL&, EGLDisplay, bool isWarp);
607 
608  public:
609   ~EglDisplay();
610 
IsExtensionSupported(EGLExtension aKnownExtension)611   bool IsExtensionSupported(EGLExtension aKnownExtension) const {
612     return mAvailableExtensions[UnderlyingValue(aKnownExtension)];
613   }
614 
MarkExtensionUnsupported(EGLExtension aKnownExtension)615   void MarkExtensionUnsupported(EGLExtension aKnownExtension) {
616     mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false;
617   }
618 
619   void DumpEGLConfig(EGLConfig) const;
620   void DumpEGLConfigs() const;
621 
622   void Shutdown();
623 
624   // -
625 
HasKHRImageBase()626   bool HasKHRImageBase() const {
627     return IsExtensionSupported(EGLExtension::KHR_image) ||
628            IsExtensionSupported(EGLExtension::KHR_image_base);
629   }
630 
HasKHRImagePixmap()631   bool HasKHRImagePixmap() const {
632     return IsExtensionSupported(EGLExtension::KHR_image) ||
633            IsExtensionSupported(EGLExtension::KHR_image_pixmap);
634   }
635 
636   // -
637 
fTerminate()638   EGLBoolean fTerminate() { return mLib->fTerminate(mDisplay); }
639 
fMakeCurrent(EGLSurface draw,EGLSurface read,EGLContext ctx)640   EGLBoolean fMakeCurrent(EGLSurface draw, EGLSurface read,
641                           EGLContext ctx) const {
642     return mLib->fMakeCurrent(mDisplay, draw, read, ctx);
643   }
644 
fDestroyContext(EGLContext ctx)645   EGLBoolean fDestroyContext(EGLContext ctx) const {
646     return mLib->fDestroyContext(mDisplay, ctx);
647   }
648 
fCreateContext(EGLConfig config,EGLContext share_context,const EGLint * attrib_list)649   EGLContext fCreateContext(EGLConfig config, EGLContext share_context,
650                             const EGLint* attrib_list) const {
651     return mLib->fCreateContext(mDisplay, config, share_context, attrib_list);
652   }
653 
fDestroySurface(EGLSurface surface)654   EGLBoolean fDestroySurface(EGLSurface surface) const {
655     return mLib->fDestroySurface(mDisplay, surface);
656   }
657 
fCreateWindowSurface(EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)658   EGLSurface fCreateWindowSurface(EGLConfig config, EGLNativeWindowType win,
659                                   const EGLint* attrib_list) const {
660     return mLib->fCreateWindowSurface(mDisplay, config, win, attrib_list);
661   }
662 
fCreatePbufferSurface(EGLConfig config,const EGLint * attrib_list)663   EGLSurface fCreatePbufferSurface(EGLConfig config,
664                                    const EGLint* attrib_list) const {
665     return mLib->fCreatePbufferSurface(mDisplay, config, attrib_list);
666   }
667 
fCreatePbufferFromClientBuffer(EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)668   EGLSurface fCreatePbufferFromClientBuffer(EGLenum buftype,
669                                             EGLClientBuffer buffer,
670                                             EGLConfig config,
671                                             const EGLint* attrib_list) const {
672     return mLib->fCreatePbufferFromClientBuffer(mDisplay, buftype, buffer,
673                                                 config, attrib_list);
674   }
675 
fChooseConfig(const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)676   EGLBoolean fChooseConfig(const EGLint* attrib_list, EGLConfig* configs,
677                            EGLint config_size, EGLint* num_config) const {
678     return mLib->fChooseConfig(mDisplay, attrib_list, configs, config_size,
679                                num_config);
680   }
681 
fGetConfigAttrib(EGLConfig config,EGLint attribute,EGLint * value)682   EGLBoolean fGetConfigAttrib(EGLConfig config, EGLint attribute,
683                               EGLint* value) const {
684     return mLib->fGetConfigAttrib(mDisplay, config, attribute, value);
685   }
686 
fGetConfigs(EGLConfig * configs,EGLint config_size,EGLint * num_config)687   EGLBoolean fGetConfigs(EGLConfig* configs, EGLint config_size,
688                          EGLint* num_config) const {
689     return mLib->fGetConfigs(mDisplay, configs, config_size, num_config);
690   }
691 
fSwapBuffers(EGLSurface surface)692   EGLBoolean fSwapBuffers(EGLSurface surface) const {
693     return mLib->fSwapBuffers(mDisplay, surface);
694   }
695 
fBindTexImage(EGLSurface surface,EGLint buffer)696   EGLBoolean fBindTexImage(EGLSurface surface, EGLint buffer) const {
697     return mLib->fBindTexImage(mDisplay, surface, buffer);
698   }
699 
fReleaseTexImage(EGLSurface surface,EGLint buffer)700   EGLBoolean fReleaseTexImage(EGLSurface surface, EGLint buffer) const {
701     return mLib->fReleaseTexImage(mDisplay, surface, buffer);
702   }
703 
fSwapInterval(EGLint interval)704   EGLBoolean fSwapInterval(EGLint interval) const {
705     return mLib->fSwapInterval(mDisplay, interval);
706   }
707 
fCreateImage(EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attribList)708   EGLImage fCreateImage(EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
709                         const EGLint* attribList) const {
710     MOZ_ASSERT(HasKHRImageBase());
711     return mLib->fCreateImage(mDisplay, ctx, target, buffer, attribList);
712   }
713 
fDestroyImage(EGLImage image)714   EGLBoolean fDestroyImage(EGLImage image) const {
715     MOZ_ASSERT(HasKHRImageBase());
716     return mLib->fDestroyImage(mDisplay, image);
717   }
718 
fQuerySurface(EGLSurface surface,EGLint attribute,EGLint * value)719   EGLBoolean fQuerySurface(EGLSurface surface, EGLint attribute,
720                            EGLint* value) const {
721     return mLib->fQuerySurface(mDisplay, surface, attribute, value);
722   }
723 
fQuerySurfacePointerANGLE(EGLSurface surface,EGLint attribute,void ** value)724   EGLBoolean fQuerySurfacePointerANGLE(EGLSurface surface, EGLint attribute,
725                                        void** value) const {
726     MOZ_ASSERT(IsExtensionSupported(
727         EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle));
728     return mLib->fQuerySurfacePointerANGLE(mDisplay, surface, attribute, value);
729   }
730 
fCreateSync(EGLenum type,const EGLint * attrib_list)731   EGLSync fCreateSync(EGLenum type, const EGLint* attrib_list) const {
732     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
733     return mLib->fCreateSync(mDisplay, type, attrib_list);
734   }
735 
fDestroySync(EGLSync sync)736   EGLBoolean fDestroySync(EGLSync sync) const {
737     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
738     return mLib->fDestroySync(mDisplay, sync);
739   }
740 
fClientWaitSync(EGLSync sync,EGLint flags,EGLTime timeout)741   EGLint fClientWaitSync(EGLSync sync, EGLint flags, EGLTime timeout) const {
742     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
743     return mLib->fClientWaitSync(mDisplay, sync, flags, timeout);
744   }
745 
fGetSyncAttrib(EGLSync sync,EGLint attribute,EGLint * value)746   EGLBoolean fGetSyncAttrib(EGLSync sync, EGLint attribute,
747                             EGLint* value) const {
748     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
749     return mLib->fGetSyncAttrib(mDisplay, sync, attribute, value);
750   }
751 
fWaitSync(EGLSync sync,EGLint flags)752   EGLint fWaitSync(EGLSync sync, EGLint flags) const {
753     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_wait_sync));
754     return mLib->fWaitSync(mDisplay, sync, flags);
755   }
756 
fDupNativeFenceFDANDROID(EGLSync sync)757   EGLint fDupNativeFenceFDANDROID(EGLSync sync) const {
758     MOZ_ASSERT(IsExtensionSupported(EGLExtension::ANDROID_native_fence_sync));
759     return mLib->fDupNativeFenceFDANDROID(mDisplay, sync);
760   }
761 
762   // EXT_device_query
fQueryDisplayAttribEXT(EGLint attribute,EGLAttrib * value)763   EGLBoolean fQueryDisplayAttribEXT(EGLint attribute, EGLAttrib* value) const {
764     MOZ_ASSERT(mLib->IsExtensionSupported(EGLLibExtension::EXT_device_query));
765     return mLib->fQueryDisplayAttribEXT(mDisplay, attribute, value);
766   }
767 
768   // KHR_stream
fCreateStreamKHR(const EGLint * attrib_list)769   EGLStreamKHR fCreateStreamKHR(const EGLint* attrib_list) const {
770     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
771     return mLib->fCreateStreamKHR(mDisplay, attrib_list);
772   }
773 
fDestroyStreamKHR(EGLStreamKHR stream)774   EGLBoolean fDestroyStreamKHR(EGLStreamKHR stream) const {
775     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
776     return mLib->fDestroyStreamKHR(mDisplay, stream);
777   }
778 
fQueryStreamKHR(EGLStreamKHR stream,EGLenum attribute,EGLint * value)779   EGLBoolean fQueryStreamKHR(EGLStreamKHR stream, EGLenum attribute,
780                              EGLint* value) const {
781     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
782     return mLib->fQueryStreamKHR(mDisplay, stream, attribute, value);
783   }
784 
785   // KHR_stream_consumer_gltexture
fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream)786   EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream) const {
787     MOZ_ASSERT(
788         IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
789     return mLib->fStreamConsumerGLTextureExternalKHR(mDisplay, stream);
790   }
791 
fStreamConsumerAcquireKHR(EGLStreamKHR stream)792   EGLBoolean fStreamConsumerAcquireKHR(EGLStreamKHR stream) const {
793     MOZ_ASSERT(
794         IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
795     return mLib->fStreamConsumerAcquireKHR(mDisplay, stream);
796   }
797 
fStreamConsumerReleaseKHR(EGLStreamKHR stream)798   EGLBoolean fStreamConsumerReleaseKHR(EGLStreamKHR stream) const {
799     MOZ_ASSERT(
800         IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
801     return mLib->fStreamConsumerReleaseKHR(mDisplay, stream);
802   }
803 
804   // NV_stream_consumer_gltexture_yuv
fStreamConsumerGLTextureExternalAttribsNV(EGLStreamKHR stream,const EGLAttrib * attrib_list)805   EGLBoolean fStreamConsumerGLTextureExternalAttribsNV(
806       EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
807     MOZ_ASSERT(
808         IsExtensionSupported(EGLExtension::NV_stream_consumer_gltexture_yuv));
809     return mLib->fStreamConsumerGLTextureExternalAttribsNV(mDisplay, stream,
810                                                            attrib_list);
811   }
812 
813   // ANGLE_stream_producer_d3d_texture
fCreateStreamProducerD3DTextureANGLE(EGLStreamKHR stream,const EGLAttrib * attrib_list)814   EGLBoolean fCreateStreamProducerD3DTextureANGLE(
815       EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
816     MOZ_ASSERT(
817         IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
818     return mLib->fCreateStreamProducerD3DTextureANGLE(mDisplay, stream,
819                                                       attrib_list);
820   }
821 
fStreamPostD3DTextureANGLE(EGLStreamKHR stream,void * texture,const EGLAttrib * attrib_list)822   EGLBoolean fStreamPostD3DTextureANGLE(EGLStreamKHR stream, void* texture,
823                                         const EGLAttrib* attrib_list) const {
824     MOZ_ASSERT(
825         IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
826     return mLib->fStreamPostD3DTextureANGLE(mDisplay, stream, texture,
827                                             attrib_list);
828   }
829 
830   // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
fSwapBuffersWithDamage(EGLSurface surface,const EGLint * rects,EGLint n_rects)831   EGLBoolean fSwapBuffersWithDamage(EGLSurface surface, const EGLint* rects,
832                                     EGLint n_rects) {
833     MOZ_ASSERT(
834         IsExtensionSupported(EGLExtension::EXT_swap_buffers_with_damage) ||
835         IsExtensionSupported(EGLExtension::KHR_swap_buffers_with_damage));
836     return mLib->fSwapBuffersWithDamage(mDisplay, surface, rects, n_rects);
837   }
838 
839   // EGL_KHR_partial_update
fSetDamageRegion(EGLSurface surface,const EGLint * rects,EGLint n_rects)840   EGLBoolean fSetDamageRegion(EGLSurface surface, const EGLint* rects,
841                               EGLint n_rects) {
842     MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_partial_update));
843     return mLib->fSetDamageRegion(mDisplay, surface, rects, n_rects);
844   }
845 };
846 
847 } /* namespace gl */
848 } /* namespace mozilla */
849 
850 #endif /* GLLIBRARYEGL_H_ */
851