/* 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 { 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, Extensions_Max }; bool IsExtensionSupported(EGLExtensions aKnownExtension) const { return mAvailableExtensions[aKnownExtension]; } void MarkExtensionUnsupported(EGLExtensions aKnownExtension) { mAvailableExtensions[aKnownExtension] = false; } protected: std::bitset 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) ) 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); 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 mReadbackGL; bool mIsANGLE; bool mIsWARP; static StaticMutex sMutex; }; extern GLLibraryEGL sEGLLibrary; #define EGL_DISPLAY() sEGLLibrary.Display() } /* namespace gl */ } /* namespace mozilla */ #endif /* GLLIBRARYEGL_H_ */