/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef GLLIBRARYEGL_H_
#define GLLIBRARYEGL_H_

#if defined(MOZ_X11)
#include "mozilla/X11Util.h"
#endif

#include "GLLibraryLoader.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/ThreadLocal.h"
#include "nsIFile.h"
#include "GeckoProfiler.h"

#include <bitset>
#include <vector>

#ifdef XP_WIN
    #ifndef WIN32_LEAN_AND_MEAN
        #define WIN32_LEAN_AND_MEAN 1
    #endif

    #include <windows.h>

    typedef HDC EGLNativeDisplayType;
    typedef HBITMAP EGLNativePixmapType;
    typedef HWND EGLNativeWindowType;
#else
    typedef void* EGLNativeDisplayType;
    typedef void* EGLNativePixmapType;
    typedef void* EGLNativeWindowType;

    #ifdef ANDROID
        // We only need to explicitly dlopen egltrace
        // on android as we can use LD_PRELOAD or other tricks
        // on other platforms. We look for it in /data/local
        // as that's writeable by all users
        //
        // This should really go in GLLibraryEGL.cpp but we currently reference
        // APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
        // will come in subsequent patches on Bug 732865
        #define APITRACE_LIB "/data/local/tmp/egltrace.so"
    #endif
#endif

#if defined(MOZ_X11)
#define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
#else
#define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)0)
#endif

namespace angle {
class Platform;
}

namespace mozilla {

namespace gfx {
class DataSourceSurface;
}

namespace gl {

class GLContext;

void BeforeEGLCall(const char* funcName);
void AfterEGLCall(const char* funcName);

class GLLibraryEGL
{
public:
    GLLibraryEGL()
        : mSymbols{nullptr}
        , mInitialized(false)
        , mEGLLibrary(nullptr)
        , mEGLDisplay(EGL_NO_DISPLAY)
        , mIsANGLE(false)
        , mIsWARP(false)
    { }

    void InitClientExtensions();
    void InitDisplayExtensions();

    /**
     * Known GL extensions that can be queried by
     * IsExtensionSupported.  The results of this are cached, and as
     * such it's safe to use this even in performance critical code.
     * If you add to this array, remember to add to the string names
     * in GLContext.cpp.
     */
    enum EGLExtensions {
        KHR_image_base,
        KHR_image_pixmap,
        KHR_gl_texture_2D_image,
        KHR_lock_surface,
        ANGLE_surface_d3d_texture_2d_share_handle,
        EXT_create_context_robustness,
        KHR_image,
        KHR_fence_sync,
        ANDROID_native_fence_sync,
        EGL_ANDROID_image_crop,
        ANGLE_platform_angle,
        ANGLE_platform_angle_d3d,
        ANGLE_d3d_share_handle_client_buffer,
        KHR_create_context,
        KHR_stream,
        KHR_stream_consumer_gltexture,
        EXT_device_base,
        EXT_device_query,
        NV_stream_consumer_gltexture_yuv,
        ANGLE_stream_producer_d3d_texture_nv12,
        Extensions_Max
    };

    bool IsExtensionSupported(EGLExtensions aKnownExtension) const {
        return mAvailableExtensions[aKnownExtension];
    }

    void MarkExtensionUnsupported(EGLExtensions aKnownExtension) {
        mAvailableExtensions[aKnownExtension] = false;
    }

protected:
    std::bitset<Extensions_Max> mAvailableExtensions;

public:
    GLLibraryLoader::PlatformLookupFunction GetLookupFunction() const {
        return (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
    }

    ////

#ifdef MOZ_WIDGET_ANDROID
#define PROFILE_CALL PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
#else
#define PROFILE_CALL
#endif

#ifndef MOZ_FUNCTION_NAME
# ifdef __GNUC__
#  define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
# elif defined(_MSC_VER)
#  define MOZ_FUNCTION_NAME __FUNCTION__
# else
#  define MOZ_FUNCTION_NAME __func__  // defined in C99, supported in various C++ compilers. Just raw function name.
# endif
#endif

#ifdef DEBUG
#define BEFORE_CALL BeforeEGLCall(MOZ_FUNCTION_NAME);
#define AFTER_CALL  AfterEGLCall(MOZ_FUNCTION_NAME);
#else
#define BEFORE_CALL
#define AFTER_CALL
#endif

#define WRAP(X) \
    { \
        PROFILE_CALL \
        BEFORE_CALL \
        const auto ret = mSymbols. X ; \
        AFTER_CALL \
        return ret; \
    }

#define VOID_WRAP(X) \
    { \
        PROFILE_CALL \
        BEFORE_CALL \
        mSymbols. X ; \
        AFTER_CALL \
    }

    EGLDisplay fGetDisplay(void* display_id) const
        WRAP(  fGetDisplay(display_id) )

    EGLDisplay fGetPlatformDisplayEXT(EGLenum platform, void* native_display, const EGLint* attrib_list) const
        WRAP(  fGetPlatformDisplayEXT(platform, native_display, attrib_list) )

    EGLBoolean fTerminate(EGLDisplay display) const
        WRAP( fTerminate(display) )

    EGLSurface fGetCurrentSurface(EGLint id) const
        WRAP(  fGetCurrentSurface(id) )

    EGLContext fGetCurrentContext() const
        WRAP(  fGetCurrentContext() )

    EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) const
        WRAP(  fMakeCurrent(dpy, draw, read, ctx) )

    EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const
        WRAP(  fDestroyContext(dpy, ctx) )

    EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list) const
        WRAP(  fCreateContext(dpy, config, share_context, attrib_list) )

    EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const
        WRAP(  fDestroySurface(dpy, surface) )

    EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list) const
        WRAP(  fCreateWindowSurface(dpy, config, win, attrib_list) )

    EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) const
        WRAP(  fCreatePbufferSurface(dpy, config, attrib_list) )

    EGLSurface fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) const
        WRAP(  fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list) )

    EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint* attrib_list) const
        WRAP(  fCreatePixmapSurface(dpy, config, pixmap, attrib_list) )

    EGLBoolean fBindAPI(EGLenum api) const
        WRAP(  fBindAPI(api) )

    EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const
        WRAP(  fInitialize(dpy, major, minor) )

    EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config) const
        WRAP(  fChooseConfig(dpy, attrib_list, configs, config_size, num_config) )

    EGLint    fGetError() const
        WRAP( fGetError() )

    EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) const
        WRAP(  fGetConfigAttrib(dpy, config, attribute, value) )

    EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) const
        WRAP(  fGetConfigs(dpy, configs, config_size, num_config) )

    EGLBoolean fWaitNative(EGLint engine) const
        WRAP(  fWaitNative(engine) )

    EGLCastToRelevantPtr fGetProcAddress(const char* procname) const
        WRAP(            fGetProcAddress(procname) )

    EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const
        WRAP(  fSwapBuffers(dpy, surface) )

    EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) const
        WRAP(  fCopyBuffers(dpy, surface, target) )

    const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const
        WRAP(      fQueryString(dpy, name) )

    EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) const
        WRAP(  fQueryContext(dpy, ctx, attribute, value) )

    EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const
        WRAP(  fBindTexImage(dpy, surface, buffer) )

    EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const
        WRAP(  fReleaseTexImage(dpy, surface, buffer) )

    EGLImage   fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list) const
        WRAP(  fCreateImageKHR(dpy, ctx, target, buffer, attrib_list) )

    EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const
        WRAP(  fDestroyImageKHR(dpy, image) )

    EGLBoolean fLockSurface(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list) const
        WRAP(  fLockSurfaceKHR(dpy, surface, attrib_list) )

    EGLBoolean fUnlockSurface(EGLDisplay dpy, EGLSurface surface) const
        WRAP(  fUnlockSurfaceKHR(dpy, surface) )

    EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value) const
        WRAP(  fQuerySurface(dpy, surface, attribute, value) )

    EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value) const
        WRAP(  fQuerySurfacePointerANGLE(dpy, surface, attribute, value) )

    EGLSync   fCreateSync(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) const
        WRAP( fCreateSyncKHR(dpy, type, attrib_list) )

    EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) const
        WRAP(  fDestroySyncKHR(dpy, sync) )

    EGLint    fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) const
        WRAP( fClientWaitSyncKHR(dpy, sync, flags, timeout) )

    EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value) const
        WRAP(  fGetSyncAttribKHR(dpy, sync, attribute, value) )

    EGLint    fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) const
        WRAP( fDupNativeFenceFDANDROID(dpy, sync) )

    //KHR_stream
    EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) const
        WRAP(    fCreateStreamKHR(dpy, attrib_list) )

    EGLStreamKHR fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const
        WRAP(    fDestroyStreamKHR(dpy, stream) )

    EGLBoolean  fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint* value) const
        WRAP(   fQueryStreamKHR(dpy, stream, attribute, value) )

    // KHR_stream_consumer_gltexture
    EGLBoolean  fStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream) const
        WRAP(   fStreamConsumerAcquireKHR(dpy, stream) )

    EGLBoolean  fStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) const
        WRAP(   fStreamConsumerReleaseKHR(dpy, stream) )

    // EXT_device_base
    EGLBoolean  fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib* value) const
        WRAP(   fQueryDisplayAttribEXT(dpy, attribute, value) )

    // EXT_device_query
    EGLBoolean  fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib* value) const
        WRAP(   fQueryDeviceAttribEXT(device, attribute, value) )

    // NV_stream_consumer_gltexture_yuv
    EGLBoolean  fStreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const
        WRAP(   fStreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list) )

    // ANGLE_stream_producer_d3d_texture_nv12
    EGLBoolean  fCreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const
        WRAP(   fCreateStreamProducerD3DTextureNV12ANGLE(dpy, stream, attrib_list) )

    EGLBoolean  fStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, EGLStreamKHR stream, void* texture, const EGLAttrib* attrib_list) const
        WRAP(   fStreamPostD3DTextureNV12ANGLE(dpy, stream, texture, attrib_list) )

    void           fANGLEPlatformInitialize(angle::Platform* platform) const
        VOID_WRAP( fANGLEPlatformInitialize(platform) )

    void fANGLEPlatformShutdown() const
        VOID_WRAP( fANGLEPlatformShutdown() )

#undef WRAP
#undef VOID_WRAP
#undef PROFILE_CALL
#undef BEFORE_CALL
#undef AFTER_CALL
#undef MOZ_FUNCTION_NAME

    ////

    EGLDisplay Display() {
        MOZ_ASSERT(mInitialized);
        return mEGLDisplay;
    }

    bool IsANGLE() const {
        MOZ_ASSERT(mInitialized);
        return mIsANGLE;
    }

    bool IsWARP() const {
        MOZ_ASSERT(mInitialized);
        return mIsWARP;
    }

    bool HasKHRImageBase() {
        return IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base);
    }

    bool HasKHRImagePixmap() {
        return IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_pixmap);
    }

    bool HasKHRImageTexture2D() {
        return IsExtensionSupported(KHR_gl_texture_2D_image);
    }

    bool HasANGLESurfaceD3DTexture2DShareHandle() {
        return IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle);
    }

    bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);

    bool EnsureInitialized(bool forceAccel, nsACString* const out_failureId);

    void DumpEGLConfig(EGLConfig cfg);
    void DumpEGLConfigs();

private:
    struct {
        EGLCastToRelevantPtr (GLAPIENTRY * fGetProcAddress)(const char* procname);
        EGLDisplay (GLAPIENTRY * fGetDisplay)(void* display_id);
        EGLDisplay (GLAPIENTRY * fGetPlatformDisplayEXT)(EGLenum platform,
                                                         void* native_display,
                                                         const EGLint* attrib_list);
        EGLBoolean (GLAPIENTRY * fTerminate)(EGLDisplay dpy);
        EGLSurface (GLAPIENTRY * fGetCurrentSurface)(EGLint);
        EGLContext (GLAPIENTRY * fGetCurrentContext)(void);
        EGLBoolean (GLAPIENTRY * fMakeCurrent)(EGLDisplay dpy, EGLSurface draw,
                                               EGLSurface read, EGLContext ctx);
        EGLBoolean (GLAPIENTRY * fDestroyContext)(EGLDisplay dpy, EGLContext ctx);
        EGLContext (GLAPIENTRY * fCreateContext)(EGLDisplay dpy, EGLConfig config,
                                                 EGLContext share_context,
                                                 const EGLint* attrib_list);
        EGLBoolean (GLAPIENTRY * fDestroySurface)(EGLDisplay dpy, EGLSurface surface);
        EGLSurface (GLAPIENTRY * fCreateWindowSurface)(EGLDisplay dpy, EGLConfig config,
                                                       EGLNativeWindowType win,
                                                       const EGLint* attrib_list);
        EGLSurface (GLAPIENTRY * fCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
                                                        const EGLint* attrib_list);
        EGLSurface (GLAPIENTRY * fCreatePbufferFromClientBuffer)(EGLDisplay dpy,
                                                                 EGLenum buftype,
                                                                 EGLClientBuffer buffer,
                                                                 EGLConfig config,
                                                                 const EGLint* attrib_list);
        EGLSurface (GLAPIENTRY * fCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config,
                                                       EGLNativePixmapType pixmap,
                                                       const EGLint* attrib_list);
        EGLBoolean (GLAPIENTRY * fBindAPI)(EGLenum api);
        EGLBoolean (GLAPIENTRY * fInitialize)(EGLDisplay dpy, EGLint* major,
                                              EGLint* minor);
        EGLBoolean (GLAPIENTRY * fChooseConfig)(EGLDisplay dpy, const EGLint* attrib_list,
                                                EGLConfig* configs, EGLint config_size,
                                                EGLint* num_config);
        EGLint     (GLAPIENTRY * fGetError)(void);
        EGLBoolean (GLAPIENTRY * fGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
                                                   EGLint attribute, EGLint* value);
        EGLBoolean (GLAPIENTRY * fGetConfigs)(EGLDisplay dpy, EGLConfig* configs,
                                              EGLint config_size, EGLint* num_config);
        EGLBoolean (GLAPIENTRY * fWaitNative)(EGLint engine);
        EGLBoolean (GLAPIENTRY * fSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
        EGLBoolean (GLAPIENTRY * fCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
                                               EGLNativePixmapType target);
        const GLubyte* (GLAPIENTRY * fQueryString)(EGLDisplay, EGLint name);
        EGLBoolean (GLAPIENTRY * fQueryContext)(EGLDisplay dpy, EGLContext ctx,
                                                EGLint attribute, EGLint* value);
        EGLBoolean (GLAPIENTRY * fBindTexImage)(EGLDisplay, EGLSurface surface,
                                                EGLint buffer);
        EGLBoolean (GLAPIENTRY * fReleaseTexImage)(EGLDisplay, EGLSurface surface,
                                                   EGLint buffer);
        EGLImage   (GLAPIENTRY * fCreateImageKHR)(EGLDisplay dpy, EGLContext ctx,
                                                  EGLenum target, EGLClientBuffer buffer,
                                                  const EGLint* attrib_list);
        EGLBoolean (GLAPIENTRY * fDestroyImageKHR)(EGLDisplay dpy, EGLImage image);
        // New extension which allow us to lock texture and get raw image pointer
        EGLBoolean (GLAPIENTRY * fLockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface,
                                                  const EGLint* attrib_list);
        EGLBoolean (GLAPIENTRY * fUnlockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface);
        EGLBoolean (GLAPIENTRY * fQuerySurface)(EGLDisplay dpy, EGLSurface surface,
                                                EGLint attribute, EGLint* value);
        EGLBoolean (GLAPIENTRY * fQuerySurfacePointerANGLE)(EGLDisplay dpy,
                                                            EGLSurface surface,
                                                            EGLint attribute,
                                                            void** value);
        EGLSync    (GLAPIENTRY * fCreateSyncKHR)(EGLDisplay dpy, EGLenum type,
                                                 const EGLint* attrib_list);
        EGLBoolean (GLAPIENTRY * fDestroySyncKHR)(EGLDisplay dpy, EGLSync sync);
        EGLint     (GLAPIENTRY * fClientWaitSyncKHR)(EGLDisplay dpy, EGLSync sync,
                                                     EGLint flags,
                                                     EGLTime timeout);
        EGLBoolean (GLAPIENTRY * fGetSyncAttribKHR)(EGLDisplay dpy, EGLSync sync,
                                                    EGLint attribute, EGLint* value);
        EGLint     (GLAPIENTRY * fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
        //KHR_stream
        EGLStreamKHR (GLAPIENTRY * fCreateStreamKHR)(EGLDisplay dpy, const EGLint* attrib_list);
        EGLStreamKHR (GLAPIENTRY * fDestroyStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream);
        EGLBoolean (GLAPIENTRY * fQueryStreamKHR)(EGLDisplay dpy,
                                                  EGLStreamKHR stream,
                                                  EGLenum attribute,
                                                  EGLint* value);
        // KHR_stream_consumer_gltexture
        EGLBoolean (GLAPIENTRY * fStreamConsumerAcquireKHR)(EGLDisplay dpy,
                                                            EGLStreamKHR stream);
        EGLBoolean (GLAPIENTRY * fStreamConsumerReleaseKHR)(EGLDisplay dpy,
                                                            EGLStreamKHR stream);
        // EXT_device_base
        EGLBoolean (GLAPIENTRY * fQueryDisplayAttribEXT)(EGLDisplay dpy,
                                                         EGLint attribute,
                                                         EGLAttrib* value);
        // EXT_device_query
        EGLBoolean (GLAPIENTRY * fQueryDeviceAttribEXT)(EGLDeviceEXT device,
                                                        EGLint attribute,
                                                        EGLAttrib* value);
        // NV_stream_consumer_gltexture_yuv
        EGLBoolean (GLAPIENTRY * fStreamConsumerGLTextureExternalAttribsNV)(EGLDisplay dpy,
                                                                            EGLStreamKHR stream,
                                                                            const EGLAttrib* attrib_list);
        // ANGLE_stream_producer_d3d_texture_nv12
        EGLBoolean (GLAPIENTRY * fCreateStreamProducerD3DTextureNV12ANGLE)(EGLDisplay dpy,
                                                                           EGLStreamKHR stream,
                                                                           const EGLAttrib* attrib_list);
        EGLBoolean (GLAPIENTRY * fStreamPostD3DTextureNV12ANGLE)(EGLDisplay dpy,
                                                                 EGLStreamKHR stream,
                                                                 void* texture,
                                                                 const EGLAttrib* attrib_list);
        void       (GLAPIENTRY * fANGLEPlatformInitialize)(angle::Platform* platform);
        void       (GLAPIENTRY * fANGLEPlatformShutdown)();
    } mSymbols;

public:
#ifdef MOZ_B2G
    EGLContext CachedCurrentContext() {
        return sCurrentContext.get();
    }
    void UnsetCachedCurrentContext() {
        sCurrentContext.set(nullptr);
    }
    void SetCachedCurrentContext(EGLContext aCtx) {
        sCurrentContext.set(aCtx);
    }
    bool CachedCurrentContextMatches() {
        return sCurrentContext.get() == fGetCurrentContext();
    }

private:
    static MOZ_THREAD_LOCAL(EGLContext) sCurrentContext;
public:

#else
    EGLContext CachedCurrentContext() {
        return nullptr;
    }
    void UnsetCachedCurrentContext() {}
    void SetCachedCurrentContext(EGLContext aCtx) { }
    bool CachedCurrentContextMatches() { return true; }
#endif

private:
    bool mInitialized;
    PRLibrary* mEGLLibrary;
    EGLDisplay mEGLDisplay;
    RefPtr<GLContext> mReadbackGL;

    bool mIsANGLE;
    bool mIsWARP;
    static StaticMutex sMutex;
};

extern GLLibraryEGL sEGLLibrary;
#define EGL_DISPLAY()        sEGLLibrary.Display()

} /* namespace gl */
} /* namespace mozilla */

#endif /* GLLIBRARYEGL_H_ */

