tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GLLibraryEGL.h (37309B)


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