gfx/gl/GLLibraryEGL.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "GLLibraryEGL.h"
     7 #include "gfxCrashReporterUtils.h"
     8 #include "mozilla/Preferences.h"
     9 #include "nsDirectoryServiceDefs.h"
    10 #include "nsDirectoryServiceUtils.h"
    11 #include "nsPrintfCString.h"
    12 #ifdef XP_WIN
    13 #include "nsWindowsHelpers.h"
    14 #endif
    15 #include "prenv.h"
    16 #include "GLContext.h"
    17 #include "gfxPrefs.h"
    19 namespace mozilla {
    20 namespace gl {
    22 GLLibraryEGL sEGLLibrary;
    24 // should match the order of EGLExtensions, and be null-terminated.
    25 static const char *sEGLExtensionNames[] = {
    26     "EGL_KHR_image_base",
    27     "EGL_KHR_image_pixmap",
    28     "EGL_KHR_gl_texture_2D_image",
    29     "EGL_KHR_lock_surface",
    30     "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
    31     "EGL_EXT_create_context_robustness",
    32     "EGL_KHR_image",
    33     "EGL_KHR_fence_sync",
    34     nullptr
    35 };
    37 #if defined(ANDROID)
    39 static PRLibrary* LoadApitraceLibrary()
    40 {
    41     if (!gfxPrefs::UseApitrace()) {
    42         return nullptr;
    43     }
    45     static PRLibrary* sApitraceLibrary = nullptr;
    47     if (sApitraceLibrary)
    48         return sApitraceLibrary;
    50     nsCString logFile = Preferences::GetCString("gfx.apitrace.logfile");
    52     if (logFile.IsEmpty()) {
    53         logFile = "firefox.trace";
    54     }
    56     // The firefox process can't write to /data/local, but it can write
    57     // to $GRE_HOME/
    58     nsAutoCString logPath;
    59     logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get());
    61     // apitrace uses the TRACE_FILE environment variable to determine where
    62     // to log trace output to
    63     printf_stderr("Logging GL tracing output to %s", logPath.get());
    64     setenv("TRACE_FILE", logPath.get(), false);
    66     printf_stderr("Attempting load of %s\n", APITRACE_LIB);
    68     sApitraceLibrary = PR_LoadLibrary(APITRACE_LIB);
    70     return sApitraceLibrary;
    71 }
    73 #endif // ANDROID
    75 #ifdef XP_WIN
    76 // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
    77 static PRLibrary*
    78 LoadLibraryForEGLOnWindows(const nsAString& filename)
    79 {
    80     nsCOMPtr<nsIFile> file;
    81 	nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
    82     if (NS_FAILED(rv))
    83         return nullptr;
    85     file->Append(filename);
    86     PRLibrary* lib = nullptr;
    87     rv = file->Load(&lib);
    88     if (NS_FAILED(rv)) {
    89         nsPrintfCString msg("Failed to load %s - Expect EGL initialization to fail",
    90                             NS_LossyConvertUTF16toASCII(filename).get());
    91         NS_WARNING(msg.get());
    92     }
    93     return lib;
    94 }
    95 #endif // XP_WIN
    97 bool
    98 GLLibraryEGL::EnsureInitialized()
    99 {
   100     if (mInitialized) {
   101         return true;
   102     }
   104     mozilla::ScopedGfxFeatureReporter reporter("EGL");
   106 #ifdef XP_WIN
   107 #ifdef MOZ_WEBGL
   108     if (!mEGLLibrary) {
   109         // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and
   110         // we should look for them there. We have to load the libs in this
   111         // order, because libEGL.dll depends on libGLESv2.dll which depends on the DXSDK
   112         // libraries. This matters especially for WebRT apps which are in a different directory.
   113         // See bug 760323 and bug 749459
   115 #ifndef MOZ_D3DCOMPILER_DLL
   116 #error MOZ_D3DCOMPILER_DLL should have been defined by the Makefile
   117 #endif
   118         // Windows 8.1 has d3dcompiler_47.dll in the system directory.
   119         // Try it first. Note that _46 will never be in the system
   120         // directory and we ship with at least _43. So there is no point
   121         // trying _46 and _43 in the system directory.
   122         if (!LoadLibrarySystem32(L"d3dcompiler_47.dll")) {
   123             // Fall back to the version that we shipped with.
   124             LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_DLL)));
   125         }
   126         // intentionally leak the D3DCOMPILER_DLL library
   128         LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
   129         // intentionally leak the libGLESv2.dll library
   131         mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
   133         if (!mEGLLibrary)
   134             return false;
   135     }
   136 #endif // MOZ_WEBGL
   137 #else // !Windows
   139     // On non-Windows (Android) we use system copies of libEGL. We look for
   140     // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
   142 #if defined(ANDROID)
   143     if (!mEGLLibrary)
   144         mEGLLibrary = LoadApitraceLibrary();
   145 #endif
   147     if (!mEGLLibrary) {
   148         printf_stderr("Attempting load of libEGL.so\n");
   149         mEGLLibrary = PR_LoadLibrary("libEGL.so");
   150     }
   151 #if defined(XP_UNIX)
   152     if (!mEGLLibrary) {
   153         mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
   154     }
   155 #endif
   157     if (!mEGLLibrary) {
   158         NS_WARNING("Couldn't load EGL LIB.");
   159         return false;
   160     }
   162 #endif // !Windows
   164 #define SYMBOL(name) \
   165 { (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }
   167     GLLibraryLoader::SymLoadStruct earlySymbols[] = {
   168         SYMBOL(GetDisplay),
   169         SYMBOL(GetCurrentSurface),
   170         SYMBOL(GetCurrentContext),
   171         SYMBOL(MakeCurrent),
   172         SYMBOL(DestroyContext),
   173         SYMBOL(CreateContext),
   174         SYMBOL(DestroySurface),
   175         SYMBOL(CreateWindowSurface),
   176         SYMBOL(CreatePbufferSurface),
   177         SYMBOL(CreatePixmapSurface),
   178         SYMBOL(BindAPI),
   179         SYMBOL(Initialize),
   180         SYMBOL(ChooseConfig),
   181         SYMBOL(GetError),
   182         SYMBOL(GetConfigs),
   183         SYMBOL(GetConfigAttrib),
   184         SYMBOL(WaitNative),
   185         SYMBOL(GetProcAddress),
   186         SYMBOL(SwapBuffers),
   187         SYMBOL(CopyBuffers),
   188         SYMBOL(QueryString),
   189         SYMBOL(QueryContext),
   190         SYMBOL(BindTexImage),
   191         SYMBOL(ReleaseTexImage),
   192         SYMBOL(QuerySurface),
   193         { nullptr, { nullptr } }
   194     };
   196     if (!GLLibraryLoader::LoadSymbols(mEGLLibrary, &earlySymbols[0])) {
   197         NS_WARNING("Couldn't find required entry points in EGL library (early init)");
   198         return false;
   199     }
   201     mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
   202     if (!fInitialize(mEGLDisplay, nullptr, nullptr))
   203         return false;
   205     const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
   206     if (vendor && (strstr(vendor, "TransGaming") != 0 || strstr(vendor, "Google Inc.") != 0)) {
   207         mIsANGLE = true;
   208     }
   210     InitExtensions();
   212     GLLibraryLoader::PlatformLookupFunction lookupFunction =
   213             (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
   215     if (IsExtensionSupported(KHR_lock_surface)) {
   216         GLLibraryLoader::SymLoadStruct lockSymbols[] = {
   217             { (PRFuncPtr*) &mSymbols.fLockSurface,   { "eglLockSurfaceKHR",   nullptr } },
   218             { (PRFuncPtr*) &mSymbols.fUnlockSurface, { "eglUnlockSurfaceKHR", nullptr } },
   219             { nullptr, { nullptr } }
   220         };
   222         bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   223                                                     &lockSymbols[0],
   224                                                     lookupFunction);
   225         if (!success) {
   226             NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");
   228             MarkExtensionUnsupported(KHR_lock_surface);
   230             mSymbols.fLockSurface = nullptr;
   231             mSymbols.fUnlockSurface = nullptr;
   232         }
   233     }
   235     if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
   236         GLLibraryLoader::SymLoadStruct d3dSymbols[] = {
   237             { (PRFuncPtr*) &mSymbols.fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", nullptr } },
   238             { nullptr, { nullptr } }
   239         };
   241         bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   242                                                     &d3dSymbols[0],
   243                                                     lookupFunction);
   244         if (!success) {
   245             NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");
   247             MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);
   249             mSymbols.fQuerySurfacePointerANGLE = nullptr;
   250         }
   251     }
   253     if (IsExtensionSupported(KHR_fence_sync)) {
   254         GLLibraryLoader::SymLoadStruct syncSymbols[] = {
   255             { (PRFuncPtr*) &mSymbols.fCreateSync,     { "eglCreateSyncKHR",     nullptr } },
   256             { (PRFuncPtr*) &mSymbols.fDestroySync,    { "eglDestroySyncKHR",    nullptr } },
   257             { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "eglClientWaitSyncKHR", nullptr } },
   258             { (PRFuncPtr*) &mSymbols.fGetSyncAttrib,  { "eglGetSyncAttribKHR",  nullptr } },
   259             { nullptr, { nullptr } }
   260         };
   262         bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   263                                                     &syncSymbols[0],
   264                                                     lookupFunction);
   265         if (!success) {
   266             NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");
   268             MarkExtensionUnsupported(KHR_fence_sync);
   270             mSymbols.fCreateSync = nullptr;
   271             mSymbols.fDestroySync = nullptr;
   272             mSymbols.fClientWaitSync = nullptr;
   273             mSymbols.fGetSyncAttrib = nullptr;
   274         }
   275     }
   277     if (IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base)) {
   278         GLLibraryLoader::SymLoadStruct imageSymbols[] = {
   279             { (PRFuncPtr*) &mSymbols.fCreateImage,  { "eglCreateImageKHR",  nullptr } },
   280             { (PRFuncPtr*) &mSymbols.fDestroyImage, { "eglDestroyImageKHR", nullptr } },
   281             { nullptr, { nullptr } }
   282         };
   284         bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   285                                                     &imageSymbols[0],
   286                                                     lookupFunction);
   287         if (!success) {
   288             NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");
   290             MarkExtensionUnsupported(KHR_image);
   291             MarkExtensionUnsupported(KHR_image_base);
   292             MarkExtensionUnsupported(KHR_image_pixmap);
   294             mSymbols.fCreateImage = nullptr;
   295             mSymbols.fDestroyImage = nullptr;
   296         }
   297     } else {
   298         MarkExtensionUnsupported(KHR_image_pixmap);
   299     }
   301     mInitialized = true;
   302     reporter.SetSuccessful();
   303     return true;
   304 }
   306 void
   307 GLLibraryEGL::InitExtensions()
   308 {
   309     const char *extensions = (const char*)fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
   311     if (!extensions) {
   312         NS_WARNING("Failed to load EGL extension list!");
   313         return;
   314     }
   316     bool debugMode = false;
   317 #ifdef DEBUG
   318     if (PR_GetEnv("MOZ_GL_DEBUG"))
   319         debugMode = true;
   321     static bool firstRun = true;
   322 #else
   323     // Non-DEBUG, so never spew.
   324     const bool firstRun = false;
   325 #endif
   327     GLContext::InitializeExtensionsBitSet(mAvailableExtensions, extensions, sEGLExtensionNames, firstRun && debugMode);
   329 #ifdef DEBUG
   330     firstRun = false;
   331 #endif
   332 }
   334 void
   335 GLLibraryEGL::DumpEGLConfig(EGLConfig cfg)
   336 {
   337     int attrval;
   338     int err;
   340 #define ATTR(_x) do {                                                   \
   341         fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval);  \
   342         if ((err = fGetError()) != 0x3000) {                        \
   343             printf_stderr("  %s: ERROR (0x%04x)\n", #_x, err);        \
   344         } else {                                                    \
   345             printf_stderr("  %s: %d (0x%04x)\n", #_x, attrval, attrval); \
   346         }                                                           \
   347     } while(0)
   349     printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
   351     ATTR(BUFFER_SIZE);
   352     ATTR(ALPHA_SIZE);
   353     ATTR(BLUE_SIZE);
   354     ATTR(GREEN_SIZE);
   355     ATTR(RED_SIZE);
   356     ATTR(DEPTH_SIZE);
   357     ATTR(STENCIL_SIZE);
   358     ATTR(CONFIG_CAVEAT);
   359     ATTR(CONFIG_ID);
   360     ATTR(LEVEL);
   361     ATTR(MAX_PBUFFER_HEIGHT);
   362     ATTR(MAX_PBUFFER_PIXELS);
   363     ATTR(MAX_PBUFFER_WIDTH);
   364     ATTR(NATIVE_RENDERABLE);
   365     ATTR(NATIVE_VISUAL_ID);
   366     ATTR(NATIVE_VISUAL_TYPE);
   367     ATTR(PRESERVED_RESOURCES);
   368     ATTR(SAMPLES);
   369     ATTR(SAMPLE_BUFFERS);
   370     ATTR(SURFACE_TYPE);
   371     ATTR(TRANSPARENT_TYPE);
   372     ATTR(TRANSPARENT_RED_VALUE);
   373     ATTR(TRANSPARENT_GREEN_VALUE);
   374     ATTR(TRANSPARENT_BLUE_VALUE);
   375     ATTR(BIND_TO_TEXTURE_RGB);
   376     ATTR(BIND_TO_TEXTURE_RGBA);
   377     ATTR(MIN_SWAP_INTERVAL);
   378     ATTR(MAX_SWAP_INTERVAL);
   379     ATTR(LUMINANCE_SIZE);
   380     ATTR(ALPHA_MASK_SIZE);
   381     ATTR(COLOR_BUFFER_TYPE);
   382     ATTR(RENDERABLE_TYPE);
   383     ATTR(CONFORMANT);
   385 #undef ATTR
   386 }
   388 void
   389 GLLibraryEGL::DumpEGLConfigs()
   390 {
   391     int nc = 0;
   392     fGetConfigs(mEGLDisplay, nullptr, 0, &nc);
   393     EGLConfig *ec = new EGLConfig[nc];
   394     fGetConfigs(mEGLDisplay, ec, nc, &nc);
   396     for (int i = 0; i < nc; ++i) {
   397         printf_stderr ("========= EGL Config %d ========\n", i);
   398         DumpEGLConfig(ec[i]);
   399     }
   401     delete [] ec;
   402 }
   404 #ifdef DEBUG
   405 /*static*/ void
   406 GLLibraryEGL::BeforeGLCall(const char* glFunction)
   407 {
   408     if (GLContext::DebugMode()) {
   409         if (GLContext::DebugMode() & GLContext::DebugTrace)
   410             printf_stderr("[egl] > %s\n", glFunction);
   411     }
   412 }
   414 /*static*/ void
   415 GLLibraryEGL::AfterGLCall(const char* glFunction)
   416 {
   417     if (GLContext::DebugMode() & GLContext::DebugTrace) {
   418         printf_stderr("[egl] < %s\n", glFunction);
   419     }
   420 }
   421 #endif
   423 } /* namespace gl */
   424 } /* namespace mozilla */

mercurial