diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 7746d065b8c9..6e14e33a11e3 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -110,94 +110,6 @@ static const char *sExtensionNames[] = { NULL }; -bool -LibrarySymbolLoader::OpenLibrary(const char *library) -{ - PRLibSpec lspec; - lspec.type = PR_LibSpec_Pathname; - lspec.value.pathname = library; - - mLibrary = PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL); - if (!mLibrary) - return false; - - return true; -} - -bool -LibrarySymbolLoader::LoadSymbols(SymLoadStruct *firstStruct, bool tryplatform, const char *prefix) -{ - return LoadSymbols(mLibrary, firstStruct, tryplatform ? mLookupFunc : nsnull, prefix); -} - -PRFuncPtr -LibrarySymbolLoader::LookupSymbol(PRLibrary *lib, - const char *sym, - PlatformLookupFunction lookupFunction) -{ - PRFuncPtr res = 0; - - // try finding it in the library directly, if we have one - if (lib) { - res = PR_FindFunctionSymbol(lib, sym); - } - - // then try looking it up via the lookup symbol - if (!res && lookupFunction) { - res = lookupFunction(sym); - } - - // finally just try finding it in the process - if (!res) { - PRLibrary *leakedLibRef; - res = PR_FindFunctionSymbolAndLibrary(sym, &leakedLibRef); - } - - return res; -} - -bool -LibrarySymbolLoader::LoadSymbols(PRLibrary *lib, - SymLoadStruct *firstStruct, - PlatformLookupFunction lookupFunction, - const char *prefix) -{ - char sbuf[MAX_SYMBOL_LENGTH * 2]; - int failCount = 0; - - SymLoadStruct *ss = firstStruct; - while (ss->symPointer) { - *ss->symPointer = 0; - - for (int i = 0; i < MAX_SYMBOL_NAMES; i++) { - if (ss->symNames[i] == nsnull) - break; - - const char *s = ss->symNames[i]; - if (prefix && *prefix != 0) { - strcpy(sbuf, prefix); - strcat(sbuf, ss->symNames[i]); - s = sbuf; - } - - PRFuncPtr p = LookupSymbol(lib, s, lookupFunction); - if (p) { - *ss->symPointer = p; - break; - } - } - - if (*ss->symPointer == 0) { - fprintf (stderr, "Can't find symbol '%s'\n", ss->symNames[0]); - failCount++; - } - - ss++; - } - - return failCount == 0 ? true : false; -} - /* * XXX - we should really know the ARB/EXT variants of these * instead of only handling the symbol if it's exposed directly. diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 2c475a07e29e..35317a1e3f0e 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -54,6 +54,7 @@ #endif #include "GLDefs.h" +#include "GLLibraryLoader.h" #include "gfxASurface.h" #include "gfxImageSurface.h" #include "gfxContext.h" @@ -84,46 +85,6 @@ namespace mozilla { namespace gl { class GLContext; -class LibrarySymbolLoader -{ -public: - bool OpenLibrary(const char *library); - - typedef PRFuncPtr (GLAPIENTRY * PlatformLookupFunction) (const char *); - - enum { - MAX_SYMBOL_NAMES = 5, - MAX_SYMBOL_LENGTH = 128 - }; - - typedef struct { - PRFuncPtr *symPointer; - const char *symNames[MAX_SYMBOL_NAMES]; - } SymLoadStruct; - - bool LoadSymbols(SymLoadStruct *firstStruct, - bool tryplatform = false, - const char *prefix = nsnull); - - /* - * Static version of the functions in this class - */ - static PRFuncPtr LookupSymbol(PRLibrary *lib, - const char *symname, - PlatformLookupFunction lookupFunction = nsnull); - static bool LoadSymbols(PRLibrary *lib, - SymLoadStruct *firstStruct, - PlatformLookupFunction lookupFunction = nsnull, - const char *prefix = nsnull); -protected: - LibrarySymbolLoader() { - mLibrary = nsnull; - mLookupFunc = nsnull; - } - - PRLibrary *mLibrary; - PlatformLookupFunction mLookupFunc; -}; enum ShaderProgramType { RGBALayerProgramType, @@ -534,7 +495,7 @@ struct THEBES_API ContextFormat }; class GLContext - : public LibrarySymbolLoader + : public GLLibraryLoader { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLContext) public: diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp index 31353ebe5098..369c7e021e59 100644 --- a/gfx/gl/GLContextProviderEGL.cpp +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -70,42 +70,23 @@ #include "AndroidBridge.h" #endif #include - -// 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 -#define APITRACE_LIB "/data/local/egltrace.so" #endif -#define EGL_LIB "libEGL.so" #define GLES2_LIB "libGLESv2.so" -#define EGL_LIB1 "libEGL.so.1" #define GLES2_LIB2 "libGLESv2.so.2" -typedef void *EGLNativeDisplayType; -typedef void *EGLNativePixmapType; -typedef void *EGLNativeWindowType; - #elif defined(XP_WIN) #include "nsILocalFile.h" +#define GLES2_LIB "libGLESv2.dll" + #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include -typedef HDC EGLNativeDisplayType; -typedef HBITMAP EGLNativePixmapType; -typedef HWND EGLNativeWindowType; - -#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW)) - -#define EGL_LIB "libEGL.dll" -#define GLES2_LIB "libGLESv2.dll" - // a little helper class AutoDestroyHWND { public: @@ -156,6 +137,7 @@ public: #include "gfxImageSurface.h" #include "gfxPlatform.h" #include "GLContextProvider.h" +#include "GLLibraryEGL.h" #include "nsDebug.h" #include "nsThreadUtils.h" #include "EGLUtils.h" @@ -177,28 +159,7 @@ extern nsIntRect gScreenBounds; namespace mozilla { namespace gl { -typedef int EGLint; -typedef unsigned int EGLBoolean; -typedef unsigned int EGLenum; -typedef void *EGLConfig; -typedef void *EGLContext; -typedef void *EGLDisplay; -typedef void *EGLSurface; -typedef void *EGLClientBuffer; -typedef void *EGLCastToRelevantPtr; -typedef void *EGLImageKHR; -typedef void *GLeglImageOES; - -#ifdef MOZ_WIDGET_QT -#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)QX11Info::display()) -#else -#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) -#endif -#define EGL_NO_CONTEXT ((EGLContext)0) -#define EGL_NO_DISPLAY ((EGLDisplay)0) -#define EGL_NO_SURFACE ((EGLSurface)0) - -#define EGL_DISPLAY() sEGLLibrary.Display() +static GLLibraryEGL sEGLLibrary; #define ADD_ATTR_2(_array, _k, _v) do { \ (_array).AppendElement(_k); \ @@ -236,38 +197,6 @@ static EGLint gContextAttribsRobustness[] = { LOCAL_EGL_NONE }; -static PRLibrary* LoadApitraceLibrary() -{ - static PRLibrary* sApitraceLibrary = NULL; - - if (sApitraceLibrary) - return sApitraceLibrary; - -#if defined(ANDROID) - nsCString logFile = Preferences::GetCString("gfx.apitrace.logfile"); - - if (logFile.IsEmpty()) { - logFile = "firefox.trace"; - } - - // The firefox process can't write to /data/local, but it can write - // to $GRE_HOME/ - nsCAutoString logPath; - logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get()); - - // apitrace uses the TRACE_FILE environment variable to determine where - // to log trace output to - printf_stderr("Logging GL tracing output to %s", logPath.get()); - setenv("TRACE_FILE", logPath.get(), false); - - printf_stderr("Attempting load of %s\n", APITRACE_LIB); - - sApitraceLibrary = PR_LoadLibrary(APITRACE_LIB); -#endif - - return sApitraceLibrary; -} - static int next_power_of_two(int v) { @@ -293,684 +222,6 @@ is_power_of_two(int v) return (v & (v-1)) == 0; } -#ifdef DEBUG -#undef BEFORE_GL_CALL -#undef AFTER_GL_CALL - -#define BEFORE_GL_CALL do { \ - BeforeGLCall(MOZ_FUNCTION_NAME); \ -} while (0) - -#define AFTER_GL_CALL do { \ - AfterGLCall(MOZ_FUNCTION_NAME); \ -} while (0) - -static void BeforeGLCall(const char* glFunction) -{ - if (GLContext::DebugMode()) { - if (GLContext::DebugMode() & GLContext::DebugTrace) - printf_stderr("[egl] > %s\n", glFunction); - } -} - -static void AfterGLCall(const char* glFunction) -{ - if (GLContext::DebugMode() & GLContext::DebugTrace) { - printf_stderr("[egl] < %s\n", glFunction); - } -} - -// We rely on the fact that GLContext.h #defines BEFORE_GL_CALL and -// AFTER_GL_CALL to nothing if !defined(DEBUG). -#endif - -static class EGLLibrary -{ -public: - EGLLibrary() - : mInitialized(false), - mEGLLibrary(nsnull), - mHasRobustness(false) - { - mIsANGLE = false; - mHave_EGL_KHR_image_base = false; - mHave_EGL_KHR_image_pixmap = false; - mHave_EGL_KHR_gl_texture_2D_image = false; - mHave_EGL_KHR_lock_surface = false; - mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle = false; - } - - struct { - typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id); - pfnGetDisplay fGetDisplay; - 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; - 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 EGLImageKHR (GLAPIENTRY * pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); - pfnCreateImageKHR fCreateImageKHR; - typedef EGLBoolean (GLAPIENTRY * pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image); - pfnDestroyImageKHR fDestroyImageKHR; -#ifdef MOZ_WIDGET_GONK - typedef EGLBoolean (GLAPIENTRY * pfnSetSwapRectangleANDROID)(EGLDisplay dpy, EGLSurface surface, EGLint left, EGLint top, EGLint width, EGLint height); - pfnSetSwapRectangleANDROID fSetSwapRectangleANDROID; -#endif - - // New extension which allow us to lock texture and get raw image pointer - typedef EGLBoolean (GLAPIENTRY * pfnLockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); - pfnLockSurfaceKHR fLockSurfaceKHR; - typedef EGLBoolean (GLAPIENTRY * pfnUnlockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface); - pfnUnlockSurfaceKHR fUnlockSurfaceKHR; - 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; - - // This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES" - // Lets keep it here for now. - typedef void (GLAPIENTRY * pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image); - pfnImageTargetTexture2DOES fImageTargetTexture2DOES; - } mSymbols; - - EGLDisplay fGetDisplay(void* display_id) - { - BEFORE_GL_CALL; - EGLDisplay disp = mSymbols.fGetDisplay(display_id); - AFTER_GL_CALL; - return disp; - } - 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 = 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; - } - EGLImageKHR fCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) - { - BEFORE_GL_CALL; - EGLImageKHR i = mSymbols.fCreateImageKHR(dpy, ctx, target, buffer, attrib_list); - AFTER_GL_CALL; - return i; - } - EGLBoolean fDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) - { - BEFORE_GL_CALL; - EGLBoolean b = mSymbols.fDestroyImageKHR(dpy, image); - AFTER_GL_CALL; - return b; - } -#ifdef MOZ_WIDGET_GONK - EGLBoolean fSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface surface, EGLint left, EGLint top, EGLint width, EGLint height) - { - BEFORE_GL_CALL; - EGLBoolean b = mSymbols.fSetSwapRectangleANDROID(dpy, surface, left, top, width, height); - AFTER_GL_CALL; - return b; - } -#endif - - // New extension which allow us to lock texture and get raw image pointer - EGLBoolean fLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list) - { - BEFORE_GL_CALL; - EGLBoolean b = mSymbols.fLockSurfaceKHR(dpy, surface, attrib_list); - AFTER_GL_CALL; - return b; - } - - EGLBoolean fUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) - { - BEFORE_GL_CALL; - EGLBoolean b = mSymbols.fUnlockSurfaceKHR(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; - } - - // This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES" - // Lets keep it here for now. - void fImageTargetTexture2DOES(GLenum target, GLeglImageOES image) - { - BEFORE_GL_CALL; - mSymbols.fImageTargetTexture2DOES(target, image); - AFTER_GL_CALL; - } - - bool EnsureInitialized() - { - if (mInitialized) { - return true; - } - - mozilla::ScopedGfxFeatureReporter reporter("EGL"); - -#ifdef XP_WIN - // Allow for explicitly specifying the location of libEGL.dll and - // libGLESv2.dll. - do { - nsCOMPtr eglFile, glesv2File; - nsresult rv = Preferences::GetComplex("gfx.angle.egl.path", - NS_GET_IID(nsILocalFile), - getter_AddRefs(eglFile)); - if (NS_FAILED(rv) || !eglFile) - break; - - nsCAutoString s; - - // note that we have to load the libs in this order, because libEGL.dll - // depends on libGLESv2.dll, but is not/may not be in our search path. - nsCOMPtr f; - eglFile->Clone(getter_AddRefs(f)); - glesv2File = do_QueryInterface(f); - if (!glesv2File) - break; - - glesv2File->Append(NS_LITERAL_STRING("libGLESv2.dll")); - - PRLibrary *glesv2lib = nsnull; // this will be leaked on purpose - glesv2File->Load(&glesv2lib); - if (!glesv2lib) - break; - - eglFile->Append(NS_LITERAL_STRING("libEGL.dll")); - eglFile->Load(&mEGLLibrary); - } while (false); -#endif - - if (!mEGLLibrary) { - mEGLLibrary = LoadApitraceLibrary(); - - if (!mEGLLibrary) { - printf_stderr("Attempting load of %s\n", EGL_LIB); - mEGLLibrary = PR_LoadLibrary(EGL_LIB); -#if defined(XP_UNIX) - if (!mEGLLibrary) { - mEGLLibrary = PR_LoadLibrary(EGL_LIB1); - } -#endif - } - } - - if (!mEGLLibrary) { - NS_WARNING("Couldn't load EGL LIB."); - return false; - } - -#define SYMBOL(name) \ - { (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, NULL } } - - LibrarySymbolLoader::SymLoadStruct earlySymbols[] = { - SYMBOL(GetDisplay), - SYMBOL(GetCurrentSurface), - SYMBOL(GetCurrentContext), - SYMBOL(MakeCurrent), - SYMBOL(DestroyContext), - SYMBOL(CreateContext), - SYMBOL(DestroySurface), - SYMBOL(CreateWindowSurface), - SYMBOL(CreatePbufferSurface), - SYMBOL(CreatePixmapSurface), - SYMBOL(BindAPI), - SYMBOL(Initialize), - SYMBOL(ChooseConfig), - SYMBOL(GetError), - SYMBOL(GetConfigs), - SYMBOL(GetConfigAttrib), - SYMBOL(WaitNative), - SYMBOL(GetProcAddress), - SYMBOL(SwapBuffers), - SYMBOL(CopyBuffers), - SYMBOL(QueryString), - SYMBOL(QueryContext), - SYMBOL(BindTexImage), - SYMBOL(ReleaseTexImage), - SYMBOL(QuerySurface), -#ifdef MOZ_WIDGET_GONK - SYMBOL(SetSwapRectangleANDROID), -#endif - { NULL, { NULL } } - }; - - if (!LibrarySymbolLoader::LoadSymbols(mEGLLibrary, &earlySymbols[0])) { - NS_WARNING("Couldn't find required entry points in EGL library (early init)"); - return false; - } - -#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE) - mEGLDisplay = fGetDisplay((EGLNativeDisplayType) gdk_x11_get_default_xdisplay()); -#else - mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY); -#endif - if (!fInitialize(mEGLDisplay, NULL, NULL)) - return false; - - const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR); - if (vendor && (strstr(vendor, "TransGaming") != 0 || strstr(vendor, "Google Inc.") != 0)) { - mIsANGLE = true; - } - - const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS); - if (!extensions) - extensions = ""; - - printf_stderr("Extensions: %s 0x%02x\n", extensions, extensions[0]); - printf_stderr("Extensions length: %d\n", strlen(extensions)); - - // note the extra space -- this ugliness tries to match - // EGL_KHR_image in the middle of the string, or right at the - // end. It's a prefix for other extensions, so we have to do - // this... - bool hasKHRImage = false; - if (strstr(extensions, "EGL_KHR_image ") || - (strlen(extensions) >= strlen("EGL_KHR_image") && - strcmp(extensions+(strlen(extensions)-strlen("EGL_KHR_image")), "EGL_KHR_image"))) - { - hasKHRImage = true; - } - - if (strstr(extensions, "EGL_KHR_image_base")) { - mHave_EGL_KHR_image_base = true; - } - - if (strstr(extensions, "EGL_KHR_image_pixmap")) { - mHave_EGL_KHR_image_pixmap = true; - - } - - if (strstr(extensions, "EGL_KHR_gl_texture_2D_image")) { - mHave_EGL_KHR_gl_texture_2D_image = true; - } - - if (strstr(extensions, "EGL_KHR_lock_surface")) { - mHave_EGL_KHR_lock_surface = true; - } - - if (hasKHRImage) { - LibrarySymbolLoader::SymLoadStruct khrSymbols[] = { - { (PRFuncPtr*) &mSymbols.fCreateImageKHR, { "eglCreateImageKHR", NULL } }, - { (PRFuncPtr*) &mSymbols.fDestroyImageKHR, { "eglDestroyImageKHR", NULL } }, - { (PRFuncPtr*) &mSymbols.fImageTargetTexture2DOES, { "glEGLImageTargetTexture2DOES", NULL } }, - { NULL, { NULL } } - }; - - LibrarySymbolLoader::LoadSymbols(mEGLLibrary, &khrSymbols[0], - (LibrarySymbolLoader::PlatformLookupFunction)mSymbols.fGetProcAddress); - } - - if (mHave_EGL_KHR_lock_surface) { - LibrarySymbolLoader::SymLoadStruct lockSymbols[] = { - { (PRFuncPtr*) &mSymbols.fLockSurfaceKHR, { "eglLockSurfaceKHR", NULL } }, - { (PRFuncPtr*) &mSymbols.fUnlockSurfaceKHR, { "eglUnlockSurfaceKHR", NULL } }, - { NULL, { NULL } } - }; - - LibrarySymbolLoader::LoadSymbols(mEGLLibrary, &lockSymbols[0], - (LibrarySymbolLoader::PlatformLookupFunction)mSymbols.fGetProcAddress); - if (!mSymbols.fLockSurfaceKHR) { - mHave_EGL_KHR_lock_surface = false; - } - } - - if (!mSymbols.fCreateImageKHR) { - mHave_EGL_KHR_image_base = false; - mHave_EGL_KHR_image_pixmap = false; - mHave_EGL_KHR_gl_texture_2D_image = false; - } - - if (!mSymbols.fImageTargetTexture2DOES) { - mHave_EGL_KHR_gl_texture_2D_image = false; - } - - if (strstr(extensions, "EGL_ANGLE_surface_d3d_texture_2d_share_handle")) { - LibrarySymbolLoader::SymLoadStruct d3dSymbols[] = { - { (PRFuncPtr*) &mSymbols.fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", NULL } }, - { NULL, { NULL } } - }; - - LibrarySymbolLoader::LoadSymbols(mEGLLibrary, &d3dSymbols[0], - (LibrarySymbolLoader::PlatformLookupFunction)mSymbols.fGetProcAddress); - if (mSymbols.fQuerySurfacePointerANGLE) { - mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle = true; - } - } - - if (strstr(extensions, "EGL_EXT_create_context_robustness")) { - mHasRobustness = true; - } - - mInitialized = true; - reporter.SetSuccessful(); - return true; - } - - EGLDisplay Display() { - return mEGLDisplay; - } - - bool IsANGLE() { - return mIsANGLE; - } - - bool HasKHRImageBase() { - return mHave_EGL_KHR_image_base; - } - - bool HasKHRImagePixmap() { - return mHave_EGL_KHR_image_pixmap; - } - - bool HasKHRImageTexture2D() { - return mHave_EGL_KHR_gl_texture_2D_image; - } - - bool HasKHRLockSurface() { - return mHave_EGL_KHR_lock_surface; - } - - bool HasANGLESurfaceD3DTexture2DShareHandle() { - return mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle; - } - - bool HasRobustness() { - return mHasRobustness; - } - - void - DumpEGLConfig(EGLConfig cfg) - { - int attrval; - int err; - -#define ATTR(_x) do { \ - fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \ - if ((err = fGetError()) != 0x3000) { \ - printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \ - } else { \ - printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \ - } \ - } while(0) - - printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg); - - ATTR(BUFFER_SIZE); - ATTR(ALPHA_SIZE); - ATTR(BLUE_SIZE); - ATTR(GREEN_SIZE); - ATTR(RED_SIZE); - ATTR(DEPTH_SIZE); - ATTR(STENCIL_SIZE); - ATTR(CONFIG_CAVEAT); - ATTR(CONFIG_ID); - ATTR(LEVEL); - ATTR(MAX_PBUFFER_HEIGHT); - ATTR(MAX_PBUFFER_PIXELS); - ATTR(MAX_PBUFFER_WIDTH); - ATTR(NATIVE_RENDERABLE); - ATTR(NATIVE_VISUAL_ID); - ATTR(NATIVE_VISUAL_TYPE); - ATTR(PRESERVED_RESOURCES); - ATTR(SAMPLES); - ATTR(SAMPLE_BUFFERS); - ATTR(SURFACE_TYPE); - ATTR(TRANSPARENT_TYPE); - ATTR(TRANSPARENT_RED_VALUE); - ATTR(TRANSPARENT_GREEN_VALUE); - ATTR(TRANSPARENT_BLUE_VALUE); - ATTR(BIND_TO_TEXTURE_RGB); - ATTR(BIND_TO_TEXTURE_RGBA); - ATTR(MIN_SWAP_INTERVAL); - ATTR(MAX_SWAP_INTERVAL); - ATTR(LUMINANCE_SIZE); - ATTR(ALPHA_MASK_SIZE); - ATTR(COLOR_BUFFER_TYPE); - ATTR(RENDERABLE_TYPE); - ATTR(CONFORMANT); - -#undef ATTR - } - - void DumpEGLConfigs() { - int nc = 0; - fGetConfigs(mEGLDisplay, NULL, 0, &nc); - EGLConfig *ec = new EGLConfig[nc]; - fGetConfigs(mEGLDisplay, ec, nc, &nc); - - for (int i = 0; i < nc; ++i) { - printf_stderr ("========= EGL Config %d ========\n", i); - DumpEGLConfig(ec[i]); - } - - delete [] ec; - } - -private: - bool mInitialized; - PRLibrary *mEGLLibrary; - EGLDisplay mEGLDisplay; - - bool mIsANGLE; - bool mHasRobustness; - - bool mHave_EGL_KHR_image_base; - bool mHave_EGL_KHR_image_pixmap; - bool mHave_EGL_KHR_gl_texture_2D_image; - bool mHave_EGL_KHR_lock_surface; - bool mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle; -} sEGLLibrary; - class GLContextEGL : public GLContext { friend class TextureImageEGL; diff --git a/gfx/gl/GLContextProviderGLX.cpp b/gfx/gl/GLContextProviderGLX.cpp index 1d4b59f78640..64258fdcdfe4 100644 --- a/gfx/gl/GLContextProviderGLX.cpp +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -51,6 +51,7 @@ #include "prenv.h" #include "GLContextProvider.h" +#include "GLLibraryLoader.h" #include "nsDebug.h" #include "nsIWidget.h" #include "GLXLibrary.h" @@ -120,7 +121,7 @@ GLXLibrary::EnsureInitialized() mDebug = true; } - LibrarySymbolLoader::SymLoadStruct symbols[] = { + GLLibraryLoader::SymLoadStruct symbols[] = { /* functions that were in GLX 1.0 */ { (PRFuncPtr*) &xDestroyContextInternal, { "glXDestroyContext", NULL } }, { (PRFuncPtr*) &xMakeCurrentInternal, { "glXMakeCurrent", NULL } }, @@ -136,7 +137,7 @@ GLXLibrary::EnsureInitialized() { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct symbols13[] = { + GLLibraryLoader::SymLoadStruct symbols13[] = { /* functions introduced in GLX 1.3 */ { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfig", NULL } }, { (PRFuncPtr*) &xGetFBConfigAttribInternal, { "glXGetFBConfigAttrib", NULL } }, @@ -150,7 +151,7 @@ GLXLibrary::EnsureInitialized() { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct symbols13_ext[] = { + GLLibraryLoader::SymLoadStruct symbols13_ext[] = { /* extension equivalents for functions introduced in GLX 1.3 */ // GLX_SGIX_fbconfig extension { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfigSGIX", NULL } }, @@ -164,31 +165,31 @@ GLXLibrary::EnsureInitialized() { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct symbols14[] = { + GLLibraryLoader::SymLoadStruct symbols14[] = { /* functions introduced in GLX 1.4 */ { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddress", NULL } }, { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct symbols14_ext[] = { + GLLibraryLoader::SymLoadStruct symbols14_ext[] = { /* extension equivalents for functions introduced in GLX 1.4 */ // GLX_ARB_get_proc_address extension { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddressARB", NULL } }, { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct symbols_texturefrompixmap[] = { + GLLibraryLoader::SymLoadStruct symbols_texturefrompixmap[] = { { (PRFuncPtr*) &xBindTexImageInternal, { "glXBindTexImageEXT", NULL } }, { (PRFuncPtr*) &xReleaseTexImageInternal, { "glXReleaseTexImageEXT", NULL } }, { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct symbols_robustness[] = { + GLLibraryLoader::SymLoadStruct symbols_robustness[] = { { (PRFuncPtr*) &xCreateContextAttribsInternal, { "glXCreateContextAttribsARB", NULL } }, { NULL, { NULL } } }; - if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &symbols[0])) { + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &symbols[0])) { NS_WARNING("Couldn't find required entry point in OpenGL shared library"); return false; } @@ -215,7 +216,7 @@ GLXLibrary::EnsureInitialized() extensionsStr = xQueryExtensionsString(display, screen); - LibrarySymbolLoader::SymLoadStruct *sym13; + GLLibraryLoader::SymLoadStruct *sym13; if (!GLXVersionCheck(1, 3)) { // Even if we don't have 1.3, we might have equivalent extensions // (as on the Intel X server). @@ -226,12 +227,12 @@ GLXLibrary::EnsureInitialized() } else { sym13 = symbols13; } - if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, sym13)) { + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, sym13)) { NS_WARNING("Couldn't find required entry point in OpenGL shared library"); return false; } - LibrarySymbolLoader::SymLoadStruct *sym14; + GLLibraryLoader::SymLoadStruct *sym14; if (!GLXVersionCheck(1, 4)) { // Even if we don't have 1.4, we might have equivalent extensions // (as on the Intel X server). @@ -242,14 +243,14 @@ GLXLibrary::EnsureInitialized() } else { sym14 = symbols14; } - if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, sym14)) { + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, sym14)) { NS_WARNING("Couldn't find required entry point in OpenGL shared library"); return false; } if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") && - LibrarySymbolLoader::LoadSymbols(mOGLLibrary, symbols_texturefrompixmap, - (LibrarySymbolLoader::PlatformLookupFunction)&xGetProcAddress)) + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_texturefrompixmap, + (GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress)) { mHasTextureFromPixmap = true; } else { @@ -257,7 +258,7 @@ GLXLibrary::EnsureInitialized() } if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness") && - LibrarySymbolLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) { + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) { mHasRobustness = true; } diff --git a/gfx/gl/GLContextProviderOSMesa.cpp b/gfx/gl/GLContextProviderOSMesa.cpp index 32190452b3b0..f6b17a5e1a30 100644 --- a/gfx/gl/GLContextProviderOSMesa.cpp +++ b/gfx/gl/GLContextProviderOSMesa.cpp @@ -37,6 +37,7 @@ #include "GLContextProvider.h" #include "GLContext.h" +#include "GLLibraryLoader.h" #include "nsDebug.h" #include "nsString.h" #include "nsIWidget.h" @@ -118,7 +119,7 @@ OSMesaLibrary::EnsureInitialized() return false; } - LibrarySymbolLoader::SymLoadStruct symbols[] = { + GLLibraryLoader::SymLoadStruct symbols[] = { { (PRFuncPtr*) &fCreateContextExt, { "OSMesaCreateContextExt", NULL } }, { (PRFuncPtr*) &fMakeCurrent, { "OSMesaMakeCurrent", NULL } }, { (PRFuncPtr*) &fPixelStore, { "OSMesaPixelStore", NULL } }, @@ -129,7 +130,7 @@ OSMesaLibrary::EnsureInitialized() { NULL, { NULL } } }; - if (!LibrarySymbolLoader::LoadSymbols(mOSMesaLibrary, &symbols[0])) { + if (!GLLibraryLoader::LoadSymbols(mOSMesaLibrary, &symbols[0])) { LogMessage("Couldn't find required entry points in OSMesa libary"); return false; } diff --git a/gfx/gl/GLContextProviderWGL.cpp b/gfx/gl/GLContextProviderWGL.cpp index f6e77b55fdf1..8df0bcaa4220 100644 --- a/gfx/gl/GLContextProviderWGL.cpp +++ b/gfx/gl/GLContextProviderWGL.cpp @@ -36,6 +36,7 @@ #include "GLContextProvider.h" #include "GLContext.h" +#include "GLLibraryLoader.h" #include "nsDebug.h" #include "nsIWidget.h" #include "WGLLibrary.h" @@ -147,7 +148,7 @@ WGLLibrary::EnsureInitialized() gUseDoubleBufferedWindows = PR_GetEnv("MOZ_WGL_DB") != nsnull; - LibrarySymbolLoader::SymLoadStruct earlySymbols[] = { + GLLibraryLoader::SymLoadStruct earlySymbols[] = { { (PRFuncPtr*) &fCreateContext, { "wglCreateContext", NULL } }, { (PRFuncPtr*) &fMakeCurrent, { "wglMakeCurrent", NULL } }, { (PRFuncPtr*) &fGetProcAddress, { "wglGetProcAddress", NULL } }, @@ -158,7 +159,7 @@ WGLLibrary::EnsureInitialized() { NULL, { NULL } } }; - if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &earlySymbols[0])) { + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &earlySymbols[0])) { NS_WARNING("Couldn't find required entry points in OpenGL DLL (early init)"); return false; } @@ -183,7 +184,7 @@ WGLLibrary::EnsureInitialized() // Now we can grab all the other symbols that we couldn't without having // a context current. - LibrarySymbolLoader::SymLoadStruct pbufferSymbols[] = { + GLLibraryLoader::SymLoadStruct pbufferSymbols[] = { { (PRFuncPtr*) &fCreatePbuffer, { "wglCreatePbufferARB", "wglCreatePbufferEXT", NULL } }, { (PRFuncPtr*) &fDestroyPbuffer, { "wglDestroyPbufferARB", "wglDestroyPbufferEXT", NULL } }, { (PRFuncPtr*) &fGetPbufferDC, { "wglGetPbufferDCARB", "wglGetPbufferDCEXT", NULL } }, @@ -192,42 +193,42 @@ WGLLibrary::EnsureInitialized() { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct pixFmtSymbols[] = { + GLLibraryLoader::SymLoadStruct pixFmtSymbols[] = { { (PRFuncPtr*) &fChoosePixelFormat, { "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT", NULL } }, { (PRFuncPtr*) &fGetPixelFormatAttribiv, { "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT", NULL } }, { NULL, { NULL } } }; - if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0], - (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress)) + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0], + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) { // this isn't an error, just means that pbuffers aren't supported fCreatePbuffer = nsnull; } - if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0], - (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress)) + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0], + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) { // this isn't an error, just means that we don't have the pixel format extension fChoosePixelFormat = nsnull; } - LibrarySymbolLoader::SymLoadStruct extensionsSymbols[] = { + GLLibraryLoader::SymLoadStruct extensionsSymbols[] = { { (PRFuncPtr *) &fGetExtensionsString, { "wglGetExtensionsStringARB", NULL} }, { NULL, { NULL } } }; - LibrarySymbolLoader::SymLoadStruct robustnessSymbols[] = { + GLLibraryLoader::SymLoadStruct robustnessSymbols[] = { { (PRFuncPtr *) &fCreateContextAttribs, { "wglCreateContextAttribsARB", NULL} }, { NULL, { NULL } } }; - if (LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0], - (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress)) { + if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0], + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) { const char *wglExts = fGetExtensionsString(gSharedWindowDC); if (wglExts && HasExtension(wglExts, "WGL_ARB_create_context")) { - LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0], - (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress); + GLLibraryLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0], + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress); if (HasExtension(wglExts, "WGL_ARB_create_context_robustness")) { mHasRobustness = true; } diff --git a/gfx/gl/GLDefs.h b/gfx/gl/GLDefs.h index ff1024c9a355..9cad4eaba99f 100644 --- a/gfx/gl/GLDefs.h +++ b/gfx/gl/GLDefs.h @@ -70,6 +70,8 @@ typedef ptrdiff_t GLsizeiptr; typedef ptrdiff_t GLintptr; #endif +#endif /* #if !defined(__gltypes_h_) && !defined(__gl_h_) */ + #ifndef GLAPIENTRY # ifdef WIN32 # define GLAPIENTRY APIENTRY @@ -80,8 +82,6 @@ typedef ptrdiff_t GLintptr; # endif #endif -#endif /* #if !defined(__gltypes_h_) && !defined(__gl_h_) */ - #define LOCAL_GL_VERSION_1_1 1 #define LOCAL_GL_ACCUM 0x0100 #define LOCAL_GL_LOAD 0x0101 diff --git a/gfx/gl/GLLibraryEGL.cpp b/gfx/gl/GLLibraryEGL.cpp new file mode 100644 index 000000000000..30cd94710561 --- /dev/null +++ b/gfx/gl/GLLibraryEGL.cpp @@ -0,0 +1,371 @@ +/* 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/. */ + +#include "GLLibraryEGL.h" + +#include "gfxCrashReporterUtils.h" +#include "mozilla/Preferences.h" + +// 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 +#define APITRACE_LIB "/data/local/egltrace.so" + +#define EGL_LIB "libEGL.so" +#define EGL_LIB1 "libEGL.so.1" + +#if defined(XP_WIN) + +#define EGL_LIB "libEGL.dll" + +#endif + +namespace mozilla { +namespace gl { + +#ifdef DEBUG +#undef BEFORE_GL_CALL +#undef AFTER_GL_CALL + +#define BEFORE_GL_CALL do { \ + BeforeGLCall(MOZ_FUNCTION_NAME); \ +} while (0) + +#define AFTER_GL_CALL do { \ + AfterGLCall(MOZ_FUNCTION_NAME); \ +} while (0) + +static void BeforeGLCall(const char* glFunction) +{ + if (GLContext::DebugMode()) { + if (GLContext::DebugMode() & GLContext::DebugTrace) + printf_stderr("[egl] > %s\n", glFunction); + } +} + +static void AfterGLCall(const char* glFunction) +{ + if (GLContext::DebugMode() & GLContext::DebugTrace) { + printf_stderr("[egl] < %s\n", glFunction); + } +} + +// We rely on the fact that GLContext.h #defines BEFORE_GL_CALL and +// AFTER_GL_CALL to nothing if !defined(DEBUG). +#endif + +static PRLibrary* LoadApitraceLibrary() +{ + static PRLibrary* sApitraceLibrary = NULL; + + if (sApitraceLibrary) + return sApitraceLibrary; + +#if defined(ANDROID) + nsCString logFile = Preferences::GetCString("gfx.apitrace.logfile"); + + if (logFile.IsEmpty()) { + logFile = "firefox.trace"; + } + + // The firefox process can't write to /data/local, but it can write + // to $GRE_HOME/ + nsCAutoString logPath; + logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get()); + + // apitrace uses the TRACE_FILE environment variable to determine where + // to log trace output to + printf_stderr("Logging GL tracing output to %s", logPath.get()); + setenv("TRACE_FILE", logPath.get(), false); + + printf_stderr("Attempting load of %s\n", APITRACE_LIB); + + sApitraceLibrary = PR_LoadLibrary(APITRACE_LIB); +#endif + + return sApitraceLibrary; +} + +bool +GLLibraryEGL::EnsureInitialized() +{ + if (mInitialized) { + return true; + } + + mozilla::ScopedGfxFeatureReporter reporter("EGL"); + +#ifdef XP_WIN + // Allow for explicitly specifying the location of libEGL.dll and + // libGLESv2.dll. + do { + nsCOMPtr eglFile, glesv2File; + nsresult rv = Preferences::GetComplex("gfx.angle.egl.path", + NS_GET_IID(nsILocalFile), + getter_AddRefs(eglFile)); + if (NS_FAILED(rv) || !eglFile) + break; + + nsCAutoString s; + + // note that we have to load the libs in this order, because libEGL.dll + // depends on libGLESv2.dll, but is not/may not be in our search path. + nsCOMPtr f; + eglFile->Clone(getter_AddRefs(f)); + glesv2File = do_QueryInterface(f); + if (!glesv2File) + break; + + glesv2File->Append(NS_LITERAL_STRING("libGLESv2.dll")); + + PRLibrary *glesv2lib = nsnull; // this will be leaked on purpose + glesv2File->Load(&glesv2lib); + if (!glesv2lib) + break; + + eglFile->Append(NS_LITERAL_STRING("libEGL.dll")); + eglFile->Load(&mEGLLibrary); + } while (false); +#endif + + if (!mEGLLibrary) { + mEGLLibrary = LoadApitraceLibrary(); + + if (!mEGLLibrary) { + printf_stderr("Attempting load of %s\n", EGL_LIB); + mEGLLibrary = PR_LoadLibrary(EGL_LIB); +#if defined(XP_UNIX) + if (!mEGLLibrary) { + mEGLLibrary = PR_LoadLibrary(EGL_LIB1); + } +#endif + } + } + + if (!mEGLLibrary) { + NS_WARNING("Couldn't load EGL LIB."); + return false; + } + +#define SYMBOL(name) \ +{ (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, NULL } } + + GLLibraryLoader::SymLoadStruct earlySymbols[] = { + SYMBOL(GetDisplay), + SYMBOL(GetCurrentSurface), + SYMBOL(GetCurrentContext), + SYMBOL(MakeCurrent), + SYMBOL(DestroyContext), + SYMBOL(CreateContext), + SYMBOL(DestroySurface), + SYMBOL(CreateWindowSurface), + SYMBOL(CreatePbufferSurface), + SYMBOL(CreatePixmapSurface), + SYMBOL(BindAPI), + SYMBOL(Initialize), + SYMBOL(ChooseConfig), + SYMBOL(GetError), + SYMBOL(GetConfigs), + SYMBOL(GetConfigAttrib), + SYMBOL(WaitNative), + SYMBOL(GetProcAddress), + SYMBOL(SwapBuffers), + SYMBOL(CopyBuffers), + SYMBOL(QueryString), + SYMBOL(QueryContext), + SYMBOL(BindTexImage), + SYMBOL(ReleaseTexImage), + SYMBOL(QuerySurface), +#ifdef MOZ_WIDGET_GONK + SYMBOL(SetSwapRectangleANDROID), +#endif + { NULL, { NULL } } + }; + + if (!GLLibraryLoader::LoadSymbols(mEGLLibrary, &earlySymbols[0])) { + NS_WARNING("Couldn't find required entry points in EGL library (early init)"); + return false; + } + +#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE) + mEGLDisplay = fGetDisplay((EGLNativeDisplayType) gdk_x11_get_default_xdisplay()); +#else + mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY); +#endif + if (!fInitialize(mEGLDisplay, NULL, NULL)) + return false; + + const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR); + if (vendor && (strstr(vendor, "TransGaming") != 0 || strstr(vendor, "Google Inc.") != 0)) { + mIsANGLE = true; + } + + const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS); + if (!extensions) + extensions = ""; + + printf_stderr("Extensions: %s 0x%02x\n", extensions, extensions[0]); + printf_stderr("Extensions length: %d\n", strlen(extensions)); + + // note the extra space -- this ugliness tries to match + // EGL_KHR_image in the middle of the string, or right at the + // end. It's a prefix for other extensions, so we have to do + // this... + bool hasKHRImage = false; + if (strstr(extensions, "EGL_KHR_image ") || + (strlen(extensions) >= strlen("EGL_KHR_image") && + strcmp(extensions+(strlen(extensions)-strlen("EGL_KHR_image")), "EGL_KHR_image"))) + { + hasKHRImage = true; + } + + if (strstr(extensions, "EGL_KHR_image_base")) { + mHave_EGL_KHR_image_base = true; + } + + if (strstr(extensions, "EGL_KHR_image_pixmap")) { + mHave_EGL_KHR_image_pixmap = true; + + } + + if (strstr(extensions, "EGL_KHR_gl_texture_2D_image")) { + mHave_EGL_KHR_gl_texture_2D_image = true; + } + + if (strstr(extensions, "EGL_KHR_lock_surface")) { + mHave_EGL_KHR_lock_surface = true; + } + + if (hasKHRImage) { + GLLibraryLoader::SymLoadStruct khrSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCreateImageKHR, { "eglCreateImageKHR", NULL } }, + { (PRFuncPtr*) &mSymbols.fDestroyImageKHR, { "eglDestroyImageKHR", NULL } }, + { (PRFuncPtr*) &mSymbols.fImageTargetTexture2DOES, { "glEGLImageTargetTexture2DOES", NULL } }, + { NULL, { NULL } } + }; + + GLLibraryLoader::LoadSymbols(mEGLLibrary, &khrSymbols[0], + (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress); + } + + if (mHave_EGL_KHR_lock_surface) { + GLLibraryLoader::SymLoadStruct lockSymbols[] = { + { (PRFuncPtr*) &mSymbols.fLockSurfaceKHR, { "eglLockSurfaceKHR", NULL } }, + { (PRFuncPtr*) &mSymbols.fUnlockSurfaceKHR, { "eglUnlockSurfaceKHR", NULL } }, + { NULL, { NULL } } + }; + + GLLibraryLoader::LoadSymbols(mEGLLibrary, &lockSymbols[0], + (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress); + if (!mSymbols.fLockSurfaceKHR) { + mHave_EGL_KHR_lock_surface = false; + } + } + + if (!mSymbols.fCreateImageKHR) { + mHave_EGL_KHR_image_base = false; + mHave_EGL_KHR_image_pixmap = false; + mHave_EGL_KHR_gl_texture_2D_image = false; + } + + if (!mSymbols.fImageTargetTexture2DOES) { + mHave_EGL_KHR_gl_texture_2D_image = false; + } + + if (strstr(extensions, "EGL_ANGLE_surface_d3d_texture_2d_share_handle")) { + GLLibraryLoader::SymLoadStruct d3dSymbols[] = { + { (PRFuncPtr*) &mSymbols.fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", NULL } }, + { NULL, { NULL } } + }; + + GLLibraryLoader::LoadSymbols(mEGLLibrary, &d3dSymbols[0], + (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress); + if (mSymbols.fQuerySurfacePointerANGLE) { + mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle = true; + } + } + + if (strstr(extensions, "EGL_EXT_create_context_robustness")) { + mHasRobustness = true; + } + + mInitialized = true; + reporter.SetSuccessful(); + return true; +} + +void +GLLibraryEGL::DumpEGLConfig(EGLConfig cfg) +{ + int attrval; + int err; + +#define ATTR(_x) do { \ + fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \ + if ((err = fGetError()) != 0x3000) { \ + printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \ + } else { \ + printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \ + } \ + } while(0) + + printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg); + + ATTR(BUFFER_SIZE); + ATTR(ALPHA_SIZE); + ATTR(BLUE_SIZE); + ATTR(GREEN_SIZE); + ATTR(RED_SIZE); + ATTR(DEPTH_SIZE); + ATTR(STENCIL_SIZE); + ATTR(CONFIG_CAVEAT); + ATTR(CONFIG_ID); + ATTR(LEVEL); + ATTR(MAX_PBUFFER_HEIGHT); + ATTR(MAX_PBUFFER_PIXELS); + ATTR(MAX_PBUFFER_WIDTH); + ATTR(NATIVE_RENDERABLE); + ATTR(NATIVE_VISUAL_ID); + ATTR(NATIVE_VISUAL_TYPE); + ATTR(PRESERVED_RESOURCES); + ATTR(SAMPLES); + ATTR(SAMPLE_BUFFERS); + ATTR(SURFACE_TYPE); + ATTR(TRANSPARENT_TYPE); + ATTR(TRANSPARENT_RED_VALUE); + ATTR(TRANSPARENT_GREEN_VALUE); + ATTR(TRANSPARENT_BLUE_VALUE); + ATTR(BIND_TO_TEXTURE_RGB); + ATTR(BIND_TO_TEXTURE_RGBA); + ATTR(MIN_SWAP_INTERVAL); + ATTR(MAX_SWAP_INTERVAL); + ATTR(LUMINANCE_SIZE); + ATTR(ALPHA_MASK_SIZE); + ATTR(COLOR_BUFFER_TYPE); + ATTR(RENDERABLE_TYPE); + ATTR(CONFORMANT); + +#undef ATTR +} + +void +GLLibraryEGL::DumpEGLConfigs() +{ + int nc = 0; + fGetConfigs(mEGLDisplay, NULL, 0, &nc); + EGLConfig *ec = new EGLConfig[nc]; + fGetConfigs(mEGLDisplay, ec, nc, &nc); + + for (int i = 0; i < nc; ++i) { + printf_stderr ("========= EGL Config %d ========\n", i); + DumpEGLConfig(ec[i]); + } + + delete [] ec; +} + +} /* namespace gl */ +} /* namespace mozilla */ + diff --git a/gfx/gl/GLLibraryEGL.h b/gfx/gl/GLLibraryEGL.h new file mode 100644 index 000000000000..c4eeca70363d --- /dev/null +++ b/gfx/gl/GLLibraryEGL.h @@ -0,0 +1,470 @@ +/* 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_ + +#include "GLContext.h" +#include "GLLibraryLoader.h" + +#include "nsILocalFile.h" + +typedef int EGLint; +typedef unsigned int EGLBoolean; +typedef unsigned int EGLenum; +typedef void *EGLConfig; +typedef void *EGLContext; +typedef void *EGLDisplay; +typedef void *EGLSurface; +typedef void *EGLClientBuffer; +typedef void *EGLCastToRelevantPtr; +typedef void *EGLImageKHR; +typedef void *GLeglImageOES; + +#ifdef ANDROID + +typedef void *EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + +#elif defined(XP_WIN) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#include + +typedef HDC EGLNativeDisplayType; +typedef HBITMAP EGLNativePixmapType; +typedef HWND EGLNativeWindowType; + +#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW)) + +#endif + +#ifdef MOZ_WIDGET_QT +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)QX11Info::display()) +#else +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) +#endif +#define EGL_NO_CONTEXT ((EGLContext)0) +#define EGL_NO_DISPLAY ((EGLDisplay)0) +#define EGL_NO_SURFACE ((EGLSurface)0) + +#define EGL_DISPLAY() sEGLLibrary.Display() + +namespace mozilla { +namespace gl { + +class GLLibraryEGL +{ +public: + GLLibraryEGL() + : mInitialized(false), + mEGLLibrary(nsnull), + mHasRobustness(false), + mIsANGLE(false), + mHave_EGL_KHR_image_base(false), + mHave_EGL_KHR_image_pixmap(false), + mHave_EGL_KHR_gl_texture_2D_image(false), + mHave_EGL_KHR_lock_surface(false), + mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle(false) + { + } + + EGLDisplay fGetDisplay(void* display_id) + { + BEFORE_GL_CALL; + EGLDisplay disp = mSymbols.fGetDisplay(display_id); + AFTER_GL_CALL; + return disp; + } + + 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 = 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; + } + + EGLImageKHR fCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) + { + BEFORE_GL_CALL; + EGLImageKHR i = mSymbols.fCreateImageKHR(dpy, ctx, target, buffer, attrib_list); + AFTER_GL_CALL; + return i; + } + + EGLBoolean fDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fDestroyImageKHR(dpy, image); + AFTER_GL_CALL; + return b; + } + +#ifdef MOZ_WIDGET_GONK + EGLBoolean fSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface surface, EGLint left, EGLint top, EGLint width, EGLint height) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fSetSwapRectangleANDROID(dpy, surface, left, top, width, height); + AFTER_GL_CALL; + return b; + } +#endif + + // New extension which allow us to lock texture and get raw image pointer + EGLBoolean fLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fLockSurfaceKHR(dpy, surface, attrib_list); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fUnlockSurfaceKHR(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; + } + + // This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES" + // Lets keep it here for now. + void fImageTargetTexture2DOES(GLenum target, GLeglImageOES image) + { + BEFORE_GL_CALL; + mSymbols.fImageTargetTexture2DOES(target, image); + AFTER_GL_CALL; + } + + EGLDisplay Display() { + return mEGLDisplay; + } + + bool IsANGLE() { + return mIsANGLE; + } + + bool HasKHRImageBase() { + return mHave_EGL_KHR_image_base; + } + + bool HasKHRImagePixmap() { + return mHave_EGL_KHR_image_pixmap; + } + + bool HasKHRImageTexture2D() { + return mHave_EGL_KHR_gl_texture_2D_image; + } + + bool HasKHRLockSurface() { + return mHave_EGL_KHR_lock_surface; + } + + bool HasANGLESurfaceD3DTexture2DShareHandle() { + return mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle; + } + + bool HasRobustness() { + return mHasRobustness; + } + + bool EnsureInitialized(); + + void DumpEGLConfig(EGLConfig cfg); + void DumpEGLConfigs(); + + struct { + typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id); + pfnGetDisplay fGetDisplay; + 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; + 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 EGLImageKHR (GLAPIENTRY * pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); + pfnCreateImageKHR fCreateImageKHR; + typedef EGLBoolean (GLAPIENTRY * pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image); + pfnDestroyImageKHR fDestroyImageKHR; +#ifdef MOZ_WIDGET_GONK + typedef EGLBoolean (GLAPIENTRY * pfnSetSwapRectangleANDROID)(EGLDisplay dpy, EGLSurface surface, EGLint left, EGLint top, EGLint width, EGLint height); + pfnSetSwapRectangleANDROID fSetSwapRectangleANDROID; +#endif + + // New extension which allow us to lock texture and get raw image pointer + typedef EGLBoolean (GLAPIENTRY * pfnLockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); + pfnLockSurfaceKHR fLockSurfaceKHR; + typedef EGLBoolean (GLAPIENTRY * pfnUnlockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface); + pfnUnlockSurfaceKHR fUnlockSurfaceKHR; + 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; + + // This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES" + // Lets keep it here for now. + typedef void (GLAPIENTRY * pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image); + pfnImageTargetTexture2DOES fImageTargetTexture2DOES; + } mSymbols; + +private: + bool mInitialized; + PRLibrary* mEGLLibrary; + EGLDisplay mEGLDisplay; + + bool mIsANGLE; + bool mHasRobustness; + + bool mHave_EGL_KHR_image_base; + bool mHave_EGL_KHR_image_pixmap; + bool mHave_EGL_KHR_gl_texture_2D_image; + bool mHave_EGL_KHR_lock_surface; + bool mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle; +}; + +} /* namespace gl */ +} /* namespace mozilla */ + +#endif /* GLLIBRARYEGL_H_ */ + diff --git a/gfx/gl/GLLibraryLoader.cpp b/gfx/gl/GLLibraryLoader.cpp new file mode 100644 index 000000000000..72b0b8f2483d --- /dev/null +++ b/gfx/gl/GLLibraryLoader.cpp @@ -0,0 +1,100 @@ +/* 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/. */ + +#include "GLLibraryLoader.h" + +namespace mozilla { +namespace gl { + +bool +GLLibraryLoader::OpenLibrary(const char *library) +{ + PRLibSpec lspec; + lspec.type = PR_LibSpec_Pathname; + lspec.value.pathname = library; + + mLibrary = PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL); + if (!mLibrary) + return false; + + return true; +} + +bool +GLLibraryLoader::LoadSymbols(SymLoadStruct *firstStruct, bool tryplatform, const char *prefix) +{ + return LoadSymbols(mLibrary, firstStruct, tryplatform ? mLookupFunc : nsnull, prefix); +} + +PRFuncPtr +GLLibraryLoader::LookupSymbol(PRLibrary *lib, + const char *sym, + PlatformLookupFunction lookupFunction) +{ + PRFuncPtr res = 0; + + // try finding it in the library directly, if we have one + if (lib) { + res = PR_FindFunctionSymbol(lib, sym); + } + + // then try looking it up via the lookup symbol + if (!res && lookupFunction) { + res = lookupFunction(sym); + } + + // finally just try finding it in the process + if (!res) { + PRLibrary *leakedLibRef; + res = PR_FindFunctionSymbolAndLibrary(sym, &leakedLibRef); + } + + return res; +} + +bool +GLLibraryLoader::LoadSymbols(PRLibrary *lib, + SymLoadStruct *firstStruct, + PlatformLookupFunction lookupFunction, + const char *prefix) +{ + char sbuf[MAX_SYMBOL_LENGTH * 2]; + int failCount = 0; + + SymLoadStruct *ss = firstStruct; + while (ss->symPointer) { + *ss->symPointer = 0; + + for (int i = 0; i < MAX_SYMBOL_NAMES; i++) { + if (ss->symNames[i] == nsnull) + break; + + const char *s = ss->symNames[i]; + if (prefix && *prefix != 0) { + strcpy(sbuf, prefix); + strcat(sbuf, ss->symNames[i]); + s = sbuf; + } + + PRFuncPtr p = LookupSymbol(lib, s, lookupFunction); + if (p) { + *ss->symPointer = p; + break; + } + } + + if (*ss->symPointer == 0) { + fprintf (stderr, "Can't find symbol '%s'\n", ss->symNames[0]); + failCount++; + } + + ss++; + } + + return failCount == 0 ? true : false; +} + +} /* namespace gl */ +} /* namespace mozilla */ + diff --git a/gfx/gl/GLLibraryLoader.h b/gfx/gl/GLLibraryLoader.h new file mode 100644 index 000000000000..1e20f16bfdcd --- /dev/null +++ b/gfx/gl/GLLibraryLoader.h @@ -0,0 +1,66 @@ +/* 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 GLLIBRARYLOADER_H_ +#define GLLIBRARYLOADER_H_ + +#include + +#ifdef WIN32 +#include +#endif + +#include "GLDefs.h" +#include "mozilla/Util.h" +#include "nscore.h" +#include "prlink.h" + +namespace mozilla { +namespace gl { + +class GLLibraryLoader +{ +public: + bool OpenLibrary(const char *library); + + typedef PRFuncPtr (GLAPIENTRY * PlatformLookupFunction) (const char *); + + enum { + MAX_SYMBOL_NAMES = 5, + MAX_SYMBOL_LENGTH = 128 + }; + + typedef struct { + PRFuncPtr *symPointer; + const char *symNames[MAX_SYMBOL_NAMES]; + } SymLoadStruct; + + bool LoadSymbols(SymLoadStruct *firstStruct, + bool tryplatform = false, + const char *prefix = nsnull); + + /* + * Static version of the functions in this class + */ + static PRFuncPtr LookupSymbol(PRLibrary *lib, + const char *symname, + PlatformLookupFunction lookupFunction = nsnull); + static bool LoadSymbols(PRLibrary *lib, + SymLoadStruct *firstStruct, + PlatformLookupFunction lookupFunction = nsnull, + const char *prefix = nsnull); +protected: + GLLibraryLoader() { + mLibrary = nsnull; + mLookupFunc = nsnull; + } + + PRLibrary *mLibrary; + PlatformLookupFunction mLookupFunc; +}; + +} /* namespace gl */ +} /* namespace mozilla */ + +#endif /* GLLIBRARYLOADER_H_ */ diff --git a/gfx/gl/Makefile.in b/gfx/gl/Makefile.in index 616af192fb34..049f0099eff3 100644 --- a/gfx/gl/Makefile.in +++ b/gfx/gl/Makefile.in @@ -51,6 +51,7 @@ EXPORTS = \ GLContextSymbols.h \ GLContextProvider.h \ GLContextProviderImpl.h \ + GLLibraryLoader.h \ EGLUtils.h \ ForceDiscreteGPUHelperCGL.h \ $(NULL) @@ -70,6 +71,7 @@ endif CPPSRCS = \ GLContext.cpp \ + GLLibraryLoader.cpp \ GLContextProviderOSMesa.cpp \ $(NULL) @@ -118,9 +120,15 @@ else CPPSRCS += GLContextProvider$(GL_PROVIDER).cpp endif +ifeq ($(GL_PROVIDER),EGL) +CPPSRCS += GLLibraryEGL.cpp +endif + # Win32 is a special snowflake, for ANGLE ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -CPPSRCS += GLContextProviderEGL.cpp +CPPSRCS += \ + GLContextProviderEGL.cpp \ + GLLibraryEGL.cpp endif ifdef MOZ_JAVA_COMPOSITOR