/* 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 #include #ifdef XP_WIN #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include 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 { #undef BEFORE_GL_CALL #undef AFTER_GL_CALL #ifdef DEBUG #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 MOZ_WIDGET_ANDROID // Record the name of the GL call for better hang stacks on Android. #define BEFORE_GL_CALL \ PROFILER_LABEL_FUNC( \ js::ProfileEntry::Category::GRAPHICS);\ BeforeGLCall(MOZ_FUNCTION_NAME) #else #define BEFORE_GL_CALL do { \ BeforeGLCall(MOZ_FUNCTION_NAME); \ } while (0) #endif #define AFTER_GL_CALL do { \ AfterGLCall(MOZ_FUNCTION_NAME); \ } while (0) #else #ifdef MOZ_WIDGET_ANDROID // Record the name of the GL call for better hang stacks on Android. #define BEFORE_GL_CALL PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS) #else #define BEFORE_GL_CALL #endif #define AFTER_GL_CALL #endif class GLContext; class GLLibraryEGL { public: GLLibraryEGL() : mInitialized(false), mEGLLibrary(nullptr), mEGLDisplay(EGL_NO_DISPLAY), mIsANGLE(false), mIsWARP(false) { ClearSymbols(); } void ClearSymbols() { mSymbols.fANGLEPlatformInitialize = nullptr; mSymbols.fANGLEPlatformShutdown = nullptr; mSymbols.fGetDisplay = nullptr; mSymbols.fGetPlatformDisplayEXT = nullptr; mSymbols.fTerminate = nullptr; mSymbols.fGetCurrentSurface = nullptr; mSymbols.fGetCurrentContext = nullptr; mSymbols.fMakeCurrent = nullptr; mSymbols.fDestroyContext = nullptr; mSymbols.fCreateContext = nullptr; mSymbols.fDestroySurface = nullptr; mSymbols.fCreateWindowSurface = nullptr; mSymbols.fCreatePbufferSurface = nullptr; mSymbols.fCreatePixmapSurface = nullptr; mSymbols.fBindAPI = nullptr; mSymbols.fInitialize = nullptr; mSymbols.fChooseConfig = nullptr; mSymbols.fGetError = nullptr; mSymbols.fGetConfigAttrib = nullptr; mSymbols.fGetConfigs = nullptr; mSymbols.fWaitNative = nullptr; mSymbols.fGetProcAddress = nullptr; mSymbols.fSwapBuffers = nullptr; mSymbols.fCopyBuffers = nullptr; mSymbols.fQueryString = nullptr; mSymbols.fQueryStringImplementationANDROID = nullptr; mSymbols.fQueryContext = nullptr; mSymbols.fBindTexImage = nullptr; mSymbols.fReleaseTexImage = nullptr; mSymbols.fCreateImage = nullptr; mSymbols.fDestroyImage = nullptr; mSymbols.fLockSurface = nullptr; mSymbols.fUnlockSurface = nullptr; mSymbols.fQuerySurface = nullptr; mSymbols.fQuerySurfacePointerANGLE = nullptr; mSymbols.fCreateSync = nullptr; mSymbols.fDestroySync = nullptr; mSymbols.fClientWaitSync = nullptr; mSymbols.fGetSyncAttrib = nullptr; mSymbols.fDupNativeFenceFDANDROID = nullptr; } 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, Extensions_Max }; bool IsExtensionSupported(EGLExtensions aKnownExtension) const { return mAvailableExtensions[aKnownExtension]; } void MarkExtensionUnsupported(EGLExtensions aKnownExtension) { mAvailableExtensions[aKnownExtension] = false; } protected: std::bitset mAvailableExtensions; public: EGLDisplay fGetDisplay(void* display_id) { BEFORE_GL_CALL; EGLDisplay disp = mSymbols.fGetDisplay(display_id); AFTER_GL_CALL; return disp; } EGLDisplay fGetPlatformDisplayEXT(EGLenum platform, void* native_display, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLDisplay disp = mSymbols.fGetPlatformDisplayEXT(platform, native_display, attrib_list); AFTER_GL_CALL; return disp; } EGLBoolean fTerminate(EGLDisplay display) { BEFORE_GL_CALL; EGLBoolean ret = mSymbols.fTerminate(display); AFTER_GL_CALL; return ret; } EGLSurface fGetCurrentSurface(EGLint id) { BEFORE_GL_CALL; EGLSurface surf = mSymbols.fGetCurrentSurface(id); AFTER_GL_CALL; return surf; } EGLContext fGetCurrentContext() { BEFORE_GL_CALL; EGLContext context = mSymbols.fGetCurrentContext(); AFTER_GL_CALL; return context; } EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fMakeCurrent(dpy, draw, read, ctx); AFTER_GL_CALL; return b; } EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fDestroyContext(dpy, ctx); AFTER_GL_CALL; return b; } EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLContext ctx = mSymbols.fCreateContext(dpy, config, share_context, attrib_list); AFTER_GL_CALL; return ctx; } EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fDestroySurface(dpy, surface); AFTER_GL_CALL; return b; } EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLSurface surf = mSymbols.fCreateWindowSurface(dpy, config, win, attrib_list); AFTER_GL_CALL; return surf; } EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLSurface surf = mSymbols.fCreatePbufferSurface(dpy, config, attrib_list); AFTER_GL_CALL; return surf; } EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLSurface surf = mSymbols.fCreatePixmapSurface(dpy, config, pixmap, attrib_list); AFTER_GL_CALL; return surf; } EGLBoolean fBindAPI(EGLenum api) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fBindAPI(api); AFTER_GL_CALL; return b; } EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fInitialize(dpy, major, minor); AFTER_GL_CALL; return b; } EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fChooseConfig(dpy, attrib_list, configs, config_size, num_config); AFTER_GL_CALL; return b; } EGLint fGetError() { BEFORE_GL_CALL; EGLint i = mSymbols.fGetError(); AFTER_GL_CALL; return i; } EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fGetConfigAttrib(dpy, config, attribute, value); AFTER_GL_CALL; return b; } EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fGetConfigs(dpy, configs, config_size, num_config); AFTER_GL_CALL; return b; } EGLBoolean fWaitNative(EGLint engine) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fWaitNative(engine); AFTER_GL_CALL; return b; } EGLCastToRelevantPtr fGetProcAddress(const char* procname) { BEFORE_GL_CALL; EGLCastToRelevantPtr p = mSymbols.fGetProcAddress(procname); AFTER_GL_CALL; return p; } EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fSwapBuffers(dpy, surface); AFTER_GL_CALL; return b; } EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fCopyBuffers(dpy, surface, target); AFTER_GL_CALL; return b; } const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) { BEFORE_GL_CALL; const GLubyte* b; if (mSymbols.fQueryStringImplementationANDROID) { b = mSymbols.fQueryStringImplementationANDROID(dpy, name); } else { b = mSymbols.fQueryString(dpy, name); } AFTER_GL_CALL; return b; } EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fQueryContext(dpy, ctx, attribute, value); AFTER_GL_CALL; return b; } EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fBindTexImage(dpy, surface, buffer); AFTER_GL_CALL; return b; } EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fReleaseTexImage(dpy, surface, buffer); AFTER_GL_CALL; return b; } EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLImage i = mSymbols.fCreateImage(dpy, ctx, target, buffer, attrib_list); AFTER_GL_CALL; return i; } EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fDestroyImage(dpy, image); AFTER_GL_CALL; return b; } // New extension which allow us to lock texture and get raw image pointer EGLBoolean fLockSurface(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fLockSurface(dpy, surface, attrib_list); AFTER_GL_CALL; return b; } EGLBoolean fUnlockSurface(EGLDisplay dpy, EGLSurface surface) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fUnlockSurface(dpy, surface); AFTER_GL_CALL; return b; } EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fQuerySurface(dpy, surface, attribute, value); AFTER_GL_CALL; return b; } EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fQuerySurfacePointerANGLE(dpy, surface, attribute, value); AFTER_GL_CALL; return b; } EGLSync fCreateSync(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) { BEFORE_GL_CALL; EGLSync ret = mSymbols.fCreateSync(dpy, type, attrib_list); AFTER_GL_CALL; return ret; } EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fDestroySync(dpy, sync); AFTER_GL_CALL; return b; } EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) { BEFORE_GL_CALL; EGLint ret = mSymbols.fClientWaitSync(dpy, sync, flags, timeout); AFTER_GL_CALL; return ret; } EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value) { BEFORE_GL_CALL; EGLBoolean b = mSymbols.fGetSyncAttrib(dpy, sync, attribute, value); AFTER_GL_CALL; return b; } EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) { MOZ_ASSERT(mSymbols.fDupNativeFenceFDANDROID); BEFORE_GL_CALL; EGLint ret = mSymbols.fDupNativeFenceFDANDROID(dpy, sync); AFTER_GL_CALL; return ret; } void fANGLEPlatformInitialize(angle::Platform* platform) { MOZ_ASSERT(mSymbols.fANGLEPlatformInitialize); BEFORE_GL_CALL; mSymbols.fANGLEPlatformInitialize(platform); AFTER_GL_CALL; } void fANGLEPlatformShutdown() { MOZ_ASSERT(mSymbols.fANGLEPlatformShutdown); BEFORE_GL_CALL; mSymbols.fANGLEPlatformShutdown(); AFTER_GL_CALL; } 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 HasRobustness() const { return IsExtensionSupported(EXT_create_context_robustness); } bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface); bool EnsureInitialized(bool forceAccel, nsACString* const out_failureId); void DumpEGLConfig(EGLConfig cfg); void DumpEGLConfigs(); struct { typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void* display_id); pfnGetDisplay fGetDisplay; typedef EGLDisplay(GLAPIENTRY * pfnGetPlatformDisplayEXT)(EGLenum platform, void* native_display, const EGLint* attrib_list); pfnGetPlatformDisplayEXT fGetPlatformDisplayEXT; typedef EGLBoolean (GLAPIENTRY * pfnTerminate)(EGLDisplay dpy); pfnTerminate fTerminate; typedef EGLSurface (GLAPIENTRY * pfnGetCurrentSurface)(EGLint); pfnGetCurrentSurface fGetCurrentSurface; typedef EGLContext (GLAPIENTRY * pfnGetCurrentContext)(void); pfnGetCurrentContext fGetCurrentContext; typedef EGLBoolean (GLAPIENTRY * pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); pfnMakeCurrent fMakeCurrent; typedef EGLBoolean (GLAPIENTRY * pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx); pfnDestroyContext fDestroyContext; typedef EGLContext (GLAPIENTRY * pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list); pfnCreateContext fCreateContext; typedef EGLBoolean (GLAPIENTRY * pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface); pfnDestroySurface fDestroySurface; typedef EGLSurface (GLAPIENTRY * pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list); pfnCreateWindowSurface fCreateWindowSurface; typedef EGLSurface (GLAPIENTRY * pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list); pfnCreatePbufferSurface fCreatePbufferSurface; typedef EGLSurface (GLAPIENTRY * pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint* attrib_list); pfnCreatePixmapSurface fCreatePixmapSurface; typedef EGLBoolean (GLAPIENTRY * pfnBindAPI)(EGLenum api); pfnBindAPI fBindAPI; typedef EGLBoolean (GLAPIENTRY * pfnInitialize)(EGLDisplay dpy, EGLint* major, EGLint* minor); pfnInitialize fInitialize; typedef EGLBoolean (GLAPIENTRY * pfnChooseConfig)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config); pfnChooseConfig fChooseConfig; typedef EGLint (GLAPIENTRY * pfnGetError)(void); pfnGetError fGetError; typedef EGLBoolean (GLAPIENTRY * pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value); pfnGetConfigAttrib fGetConfigAttrib; typedef EGLBoolean (GLAPIENTRY * pfnGetConfigs)(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config); pfnGetConfigs fGetConfigs; typedef EGLBoolean (GLAPIENTRY * pfnWaitNative)(EGLint engine); pfnWaitNative fWaitNative; typedef EGLCastToRelevantPtr (GLAPIENTRY * pfnGetProcAddress)(const char* procname); pfnGetProcAddress fGetProcAddress; typedef EGLBoolean (GLAPIENTRY * pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface); pfnSwapBuffers fSwapBuffers; typedef EGLBoolean (GLAPIENTRY * pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); pfnCopyBuffers fCopyBuffers; typedef const GLubyte* (GLAPIENTRY * pfnQueryString)(EGLDisplay, EGLint name); pfnQueryString fQueryString; pfnQueryString fQueryStringImplementationANDROID; typedef EGLBoolean (GLAPIENTRY * pfnQueryContext)(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value); pfnQueryContext fQueryContext; typedef EGLBoolean (GLAPIENTRY * pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer); pfnBindTexImage fBindTexImage; typedef EGLBoolean (GLAPIENTRY * pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer); pfnReleaseTexImage fReleaseTexImage; typedef EGLImage (GLAPIENTRY * pfnCreateImage)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list); pfnCreateImage fCreateImage; typedef EGLBoolean (GLAPIENTRY * pfnDestroyImage)(EGLDisplay dpy, EGLImage image); pfnDestroyImage fDestroyImage; // New extension which allow us to lock texture and get raw image pointer typedef EGLBoolean (GLAPIENTRY * pfnLockSurface)(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list); pfnLockSurface fLockSurface; typedef EGLBoolean (GLAPIENTRY * pfnUnlockSurface)(EGLDisplay dpy, EGLSurface surface); pfnUnlockSurface fUnlockSurface; typedef EGLBoolean (GLAPIENTRY * pfnQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value); pfnQuerySurface fQuerySurface; typedef EGLBoolean (GLAPIENTRY * pfnQuerySurfacePointerANGLE)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value); pfnQuerySurfacePointerANGLE fQuerySurfacePointerANGLE; typedef EGLSync (GLAPIENTRY * pfnCreateSync)(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list); pfnCreateSync fCreateSync; typedef EGLBoolean (GLAPIENTRY * pfnDestroySync)(EGLDisplay dpy, EGLSync sync); pfnDestroySync fDestroySync; typedef EGLint (GLAPIENTRY * pfnClientWaitSync)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); pfnClientWaitSync fClientWaitSync; typedef EGLBoolean (GLAPIENTRY * pfnGetSyncAttrib)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value); pfnGetSyncAttrib fGetSyncAttrib; typedef EGLint (GLAPIENTRY * pfnDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync); pfnDupNativeFenceFDANDROID fDupNativeFenceFDANDROID; typedef void (GLAPIENTRY * pfnANGLEPlatformInitialize)(angle::Platform* platform); pfnANGLEPlatformInitialize fANGLEPlatformInitialize; typedef void (GLAPIENTRY * pfnANGLEPlatformShutdown)(); pfnANGLEPlatformShutdown fANGLEPlatformShutdown; } mSymbols; #ifdef DEBUG static void BeforeGLCall(const char* glFunction); static void AfterGLCall(const char* glFunction); #endif EGLContext CachedCurrentContext() { return nullptr; } void UnsetCachedCurrentContext() {} void SetCachedCurrentContext(EGLContext aCtx) { } bool CachedCurrentContextMatches() { return true; } private: bool mInitialized; PRLibrary* mEGLLibrary; EGLDisplay mEGLDisplay; RefPtr mReadbackGL; bool mIsANGLE; bool mIsWARP; static StaticMutex sMutex; }; extern GLLibraryEGL sEGLLibrary; #define EGL_DISPLAY() sEGLLibrary.Display() } /* namespace gl */ } /* namespace mozilla */ #endif /* GLLIBRARYEGL_H_ */