LCOV - code coverage report
Current view: top level - gfx/gl - GLLibraryEGL.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 6 372 1.6 %
Date: 2017-07-14 16:53:18 Functions: 1 21 4.8 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       4             : 
       5             : #include "GLLibraryEGL.h"
       6             : 
       7             : #include "angle/Platform.h"
       8             : #include "gfxConfig.h"
       9             : #include "gfxCrashReporterUtils.h"
      10             : #include "gfxUtils.h"
      11             : #include "mozilla/Preferences.h"
      12             : #include "mozilla/Assertions.h"
      13             : #include "mozilla/Telemetry.h"
      14             : #include "mozilla/Tokenizer.h"
      15             : #include "mozilla/ScopeExit.h"
      16             : #include "mozilla/Unused.h"
      17             : #include "mozilla/webrender/RenderThread.h"
      18             : #include "nsDirectoryServiceDefs.h"
      19             : #include "nsDirectoryServiceUtils.h"
      20             : #include "nsIGfxInfo.h"
      21             : #include "nsPrintfCString.h"
      22             : #ifdef XP_WIN
      23             : #include "nsWindowsHelpers.h"
      24             : #endif
      25             : #include "OGLShaderProgram.h"
      26             : #include "prenv.h"
      27             : #include "prsystem.h"
      28             : #include "GLContext.h"
      29             : #include "GLContextProvider.h"
      30             : #include "gfxPrefs.h"
      31             : #include "ScopedGLHelpers.h"
      32             : 
      33             : namespace mozilla {
      34             : namespace gl {
      35             : 
      36           3 : StaticMutex GLLibraryEGL::sMutex;
      37           3 : GLLibraryEGL sEGLLibrary;
      38             : #ifdef MOZ_B2G
      39             : MOZ_THREAD_LOCAL(EGLContext) GLLibraryEGL::sCurrentContext;
      40             : #endif
      41             : 
      42             : // should match the order of EGLExtensions, and be null-terminated.
      43             : static const char* sEGLExtensionNames[] = {
      44             :     "EGL_KHR_image_base",
      45             :     "EGL_KHR_image_pixmap",
      46             :     "EGL_KHR_gl_texture_2D_image",
      47             :     "EGL_KHR_lock_surface",
      48             :     "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
      49             :     "EGL_EXT_create_context_robustness",
      50             :     "EGL_KHR_image",
      51             :     "EGL_KHR_fence_sync",
      52             :     "EGL_ANDROID_native_fence_sync",
      53             :     "EGL_ANDROID_image_crop",
      54             :     "EGL_ANGLE_platform_angle",
      55             :     "EGL_ANGLE_platform_angle_d3d",
      56             :     "EGL_ANGLE_d3d_share_handle_client_buffer",
      57             :     "EGL_KHR_create_context",
      58             :     "EGL_KHR_stream",
      59             :     "EGL_KHR_stream_consumer_gltexture",
      60             :     "EGL_EXT_device_base",
      61             :     "EGL_EXT_device_query",
      62             :     "EGL_NV_stream_consumer_gltexture_yuv",
      63             :     "EGL_ANGLE_stream_producer_d3d_texture_nv12",
      64             : };
      65             : 
      66             : #if defined(ANDROID)
      67             : 
      68             : static PRLibrary* LoadApitraceLibrary()
      69             : {
      70             :     // Initialization of gfx prefs here is only needed during the unit tests...
      71             :     gfxPrefs::GetSingleton();
      72             :     if (!gfxPrefs::UseApitrace()) {
      73             :         return nullptr;
      74             :     }
      75             : 
      76             :     static PRLibrary* sApitraceLibrary = nullptr;
      77             : 
      78             :     if (sApitraceLibrary)
      79             :         return sApitraceLibrary;
      80             : 
      81             :     nsCString logFile = Preferences::GetCString("gfx.apitrace.logfile");
      82             : 
      83             :     if (logFile.IsEmpty()) {
      84             :         logFile = "firefox.trace";
      85             :     }
      86             : 
      87             :     // The firefox process can't write to /data/local, but it can write
      88             :     // to $GRE_HOME/
      89             :     nsAutoCString logPath;
      90             :     logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get());
      91             : 
      92             :     // apitrace uses the TRACE_FILE environment variable to determine where
      93             :     // to log trace output to
      94             :     printf_stderr("Logging GL tracing output to %s", logPath.get());
      95             :     setenv("TRACE_FILE", logPath.get(), false);
      96             : 
      97             :     printf_stderr("Attempting load of %s\n", APITRACE_LIB);
      98             : 
      99             :     sApitraceLibrary = PR_LoadLibrary(APITRACE_LIB);
     100             : 
     101             :     return sApitraceLibrary;
     102             : }
     103             : 
     104             : #endif // ANDROID
     105             : 
     106             : #ifdef XP_WIN
     107             : // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
     108             : static PRLibrary*
     109             : LoadLibraryForEGLOnWindows(const nsAString& filename)
     110             : {
     111             :     nsAutoCString path(gfx::gfxVars::GREDirectory());
     112             :     path.Append(PR_GetDirectorySeparator());
     113             :     path.Append(ToNewUTF8String(filename));
     114             : 
     115             :     PRLibSpec lspec;
     116             :     lspec.type = PR_LibSpec_Pathname;
     117             :     lspec.value.pathname = path.get();
     118             :     return PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL);
     119             : }
     120             : 
     121             : #endif // XP_WIN
     122             : 
     123             : static EGLDisplay
     124           0 : GetAndInitWARPDisplay(GLLibraryEGL& egl, void* displayType)
     125             : {
     126             :     EGLint attrib_list[] = {  LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
     127             :                               LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
     128             :                               // Requires:
     129             :                               LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
     130             :                               LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
     131           0 :                               LOCAL_EGL_NONE };
     132             :     EGLDisplay display = egl.fGetPlatformDisplayEXT(LOCAL_EGL_PLATFORM_ANGLE_ANGLE,
     133             :                                                     displayType,
     134           0 :                                                     attrib_list);
     135             : 
     136           0 :     if (display == EGL_NO_DISPLAY) {
     137           0 :         const EGLint err = egl.fGetError();
     138           0 :         if (err != LOCAL_EGL_SUCCESS) {
     139           0 :             gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err);
     140           0 :             MOZ_CRASH("GFX: Unexpected GL error.");
     141             :         }
     142           0 :         return EGL_NO_DISPLAY;
     143             :     }
     144             : 
     145           0 :     if (!egl.fInitialize(display, nullptr, nullptr))
     146           0 :         return EGL_NO_DISPLAY;
     147             : 
     148           0 :     return display;
     149             : }
     150             : 
     151             : static bool
     152           0 : IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
     153             :                       nsACString* const out_failureId)
     154             : {
     155           0 :     if (wr::RenderThread::IsInRenderThread()) {
     156             :         // We can only enter here with WebRender, so assert that this is a
     157             :         // WebRender-enabled build.
     158             : #ifndef MOZ_BUILD_WEBRENDER
     159             :         MOZ_ASSERT(false);
     160             : #endif
     161           0 :         return true;
     162             :     }
     163             :     int32_t angleSupport;
     164           0 :     nsCString failureId;
     165             :     gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
     166             :                                          nsIGfxInfo::FEATURE_WEBGL_ANGLE,
     167             :                                          failureId,
     168           0 :                                          &angleSupport);
     169           0 :     if (failureId.IsEmpty() && angleSupport != nsIGfxInfo::FEATURE_STATUS_OK) {
     170             :         // This shouldn't happen, if we see this it's because we've missed
     171             :         // some failure paths
     172           0 :         failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_ACCL_ANGLE_NOT_OK");
     173             :     }
     174           0 :     if (out_failureId->IsEmpty()) {
     175           0 :         *out_failureId = failureId;
     176             :     }
     177           0 :     return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK);
     178             : }
     179             : 
     180             : static EGLDisplay
     181           0 : GetAndInitDisplay(GLLibraryEGL& egl, void* displayType)
     182             : {
     183           0 :     EGLDisplay display = egl.fGetDisplay(displayType);
     184           0 :     if (display == EGL_NO_DISPLAY)
     185           0 :         return EGL_NO_DISPLAY;
     186             : 
     187           0 :     if (!egl.fInitialize(display, nullptr, nullptr))
     188           0 :         return EGL_NO_DISPLAY;
     189             : 
     190           0 :     return display;
     191             : }
     192             : 
     193           0 : class AngleErrorReporting: public angle::Platform {
     194             : public:
     195           3 :     AngleErrorReporting()
     196           3 :     {
     197             :       // No static constructor
     198           3 :     }
     199             : 
     200           0 :     void SetFailureId(nsACString* const aFailureId)
     201             :     {
     202           0 :       mFailureId = aFailureId;
     203           0 :     }
     204             : 
     205           0 :     void logError(const char *errorMessage) override
     206             :     {
     207           0 :         if (!mFailureId) {
     208           0 :             return;
     209             :         }
     210             : 
     211           0 :         nsCString str(errorMessage);
     212           0 :         Tokenizer tokenizer(str);
     213             : 
     214             :         // Parse "ANGLE Display::initialize error " << error.getID() << ": "
     215             :         //       << error.getMessage()
     216           0 :         nsCString currWord;
     217           0 :         Tokenizer::Token intToken;
     218           0 :         if (tokenizer.CheckWord("ANGLE") &&
     219           0 :             tokenizer.CheckWhite() &&
     220           0 :             tokenizer.CheckWord("Display") &&
     221           0 :             tokenizer.CheckChar(':') &&
     222           0 :             tokenizer.CheckChar(':') &&
     223           0 :             tokenizer.CheckWord("initialize") &&
     224           0 :             tokenizer.CheckWhite() &&
     225           0 :             tokenizer.CheckWord("error") &&
     226           0 :             tokenizer.CheckWhite() &&
     227           0 :             tokenizer.Check(Tokenizer::TOKEN_INTEGER, intToken)) {
     228           0 :             *mFailureId = "FAILURE_ID_ANGLE_ID_";
     229           0 :             mFailureId->AppendPrintf("%" PRIu64, intToken.AsInteger());
     230             :         } else {
     231           0 :             *mFailureId = "FAILURE_ID_ANGLE_UNKNOWN";
     232             :         }
     233             :     }
     234             : private:
     235             :     nsACString* mFailureId;
     236             : };
     237             : 
     238           3 : AngleErrorReporting gAngleErrorReporter;
     239             : 
     240             : static EGLDisplay
     241           0 : GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl, nsACString* const out_failureId)
     242             : {
     243           0 :     EGLDisplay ret = 0;
     244             : 
     245           0 :     if (wr::RenderThread::IsInRenderThread()) {
     246           0 :         return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
     247             :     }
     248             : 
     249           0 :     FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
     250             : 
     251           0 :     if (!gfxPrefs::WebGLANGLETryD3D11())
     252           0 :         d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref",
     253           0 :                                NS_LITERAL_CSTRING("FAILURE_ID_ANGLE_PREF"));
     254             : 
     255           0 :     if (gfxPrefs::WebGLANGLEForceD3D11())
     256           0 :         d3d11ANGLE.UserForceEnable("User force-enabled D3D11 ANGLE on disabled hardware");
     257             : 
     258           0 :     gAngleErrorReporter.SetFailureId(out_failureId);
     259           0 :     egl.fANGLEPlatformInitialize(&gAngleErrorReporter);
     260             : 
     261           0 :     auto guardShutdown = mozilla::MakeScopeExit([&] {
     262           0 :         gAngleErrorReporter.SetFailureId(nullptr);
     263             :         // NOTE: Ideally we should be calling ANGLEPlatformShutdown after the
     264             :         //       ANGLE display is destroyed. However gAngleErrorReporter
     265             :         //       will live longer than the ANGLE display so we're fine.
     266           0 :     });
     267             : 
     268           0 :     if (gfxConfig::IsForcedOnByUser(Feature::D3D11_HW_ANGLE)) {
     269           0 :         return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
     270             :     }
     271             : 
     272           0 :     if (d3d11ANGLE.IsEnabled()) {
     273           0 :         ret = GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
     274             :     }
     275             : 
     276           0 :     if (!ret) {
     277           0 :         ret = GetAndInitDisplay(egl, EGL_DEFAULT_DISPLAY);
     278             :     }
     279             : 
     280           0 :     if (!ret && out_failureId->IsEmpty()) {
     281           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_ACCL_ANGLE_NO_DISP");
     282             :     }
     283             : 
     284           0 :     return ret;
     285             : }
     286             : 
     287             : bool
     288           0 : GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface)
     289             : {
     290           0 :     StaticMutexAutoUnlock lock(sMutex);
     291           0 :     if (!mReadbackGL) {
     292           0 :         nsCString discardFailureId;
     293           0 :         mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE,
     294           0 :                                                             &discardFailureId);
     295             :     }
     296             : 
     297           0 :     ScopedTexture destTex(mReadbackGL);
     298           0 :     const GLuint target = mReadbackGL->GetPreferredEGLImageTextureTarget();
     299           0 :     ScopedBindTexture autoTex(mReadbackGL, destTex.Texture(), target);
     300           0 :     mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
     301           0 :     mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
     302           0 :     mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
     303           0 :     mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
     304           0 :     mReadbackGL->fEGLImageTargetTexture2D(target, image);
     305             : 
     306             :     ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(target,
     307           0 :                                                              out_surface->GetFormat());
     308           0 :     int shaderConfig = config.mFeatures;
     309           0 :     mReadbackGL->ReadTexImageHelper()->ReadTexImage(out_surface, 0, target,
     310           0 :                                                     out_surface->GetSize(), shaderConfig);
     311             : 
     312           0 :     return true;
     313             : }
     314             : 
     315             : bool
     316           0 : GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId)
     317             : {
     318           0 :     if (mInitialized) {
     319           0 :         return true;
     320             :     }
     321             : 
     322           0 :     mozilla::ScopedGfxFeatureReporter reporter("EGL");
     323             : 
     324             : #ifdef MOZ_B2G
     325             :     if (!sCurrentContext.init())
     326             :       MOZ_CRASH("GFX: Tls init failed");
     327             : #endif
     328             : 
     329             : #ifdef XP_WIN
     330             :     if (!mEGLLibrary) {
     331             :         // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and
     332             :         // we should look for them there. We have to load the libs in this
     333             :         // order, because libEGL.dll depends on libGLESv2.dll which depends on the DXSDK
     334             :         // libraries. This matters especially for WebRT apps which are in a different directory.
     335             :         // See bug 760323 and bug 749459
     336             : 
     337             :         // Also note that we intentionally leak the libs we load.
     338             : 
     339             :         do {
     340             :             // Windows 8.1+ has d3dcompiler_47.dll in the system directory.
     341             :             // Try it first. Note that _46 will never be in the system
     342             :             // directory. So there is no point trying _46 in the system
     343             :             // directory.
     344             : 
     345             :             if (LoadLibrarySystem32(L"d3dcompiler_47.dll"))
     346             :                 break;
     347             : 
     348             : #ifdef MOZ_D3DCOMPILER_VISTA_DLL
     349             :             if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL))))
     350             :                 break;
     351             : #endif
     352             : 
     353             :             MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
     354             :         } while (false);
     355             : 
     356             :         LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
     357             : 
     358             :         mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
     359             : 
     360             :         if (!mEGLLibrary) {
     361             :             *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_LOAD");
     362             :             return false;
     363             :         }
     364             :     }
     365             : 
     366             : #else // !Windows
     367             : 
     368             :     // On non-Windows (Android) we use system copies of libEGL. We look for
     369             :     // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
     370             : 
     371             : #if defined(ANDROID)
     372             :     if (!mEGLLibrary)
     373             :         mEGLLibrary = LoadApitraceLibrary();
     374             : #endif
     375             : 
     376           0 :     if (!mEGLLibrary) {
     377           0 :         printf_stderr("Attempting load of libEGL.so\n");
     378           0 :         mEGLLibrary = PR_LoadLibrary("libEGL.so");
     379             :     }
     380             : #if defined(XP_UNIX)
     381           0 :     if (!mEGLLibrary) {
     382           0 :         mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
     383             :     }
     384             : #endif
     385             : 
     386           0 :     if (!mEGLLibrary) {
     387           0 :         NS_WARNING("Couldn't load EGL LIB.");
     388           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_LOAD_2");
     389           0 :         return false;
     390             :     }
     391             : 
     392             : #endif // !Windows
     393             : 
     394             : #define SYMBOL(X) { (PRFuncPtr*)&mSymbols.f##X, { "egl" #X, nullptr } }
     395             : #define END_OF_SYMBOLS { nullptr, { nullptr } }
     396             : 
     397             :     GLLibraryLoader::SymLoadStruct earlySymbols[] = {
     398           0 :         SYMBOL(GetDisplay),
     399           0 :         SYMBOL(Terminate),
     400           0 :         SYMBOL(GetCurrentSurface),
     401           0 :         SYMBOL(GetCurrentContext),
     402           0 :         SYMBOL(MakeCurrent),
     403           0 :         SYMBOL(DestroyContext),
     404           0 :         SYMBOL(CreateContext),
     405           0 :         SYMBOL(DestroySurface),
     406           0 :         SYMBOL(CreateWindowSurface),
     407           0 :         SYMBOL(CreatePbufferSurface),
     408           0 :         SYMBOL(CreatePbufferFromClientBuffer),
     409           0 :         SYMBOL(CreatePixmapSurface),
     410           0 :         SYMBOL(BindAPI),
     411           0 :         SYMBOL(Initialize),
     412           0 :         SYMBOL(ChooseConfig),
     413           0 :         SYMBOL(GetError),
     414           0 :         SYMBOL(GetConfigs),
     415           0 :         SYMBOL(GetConfigAttrib),
     416           0 :         SYMBOL(WaitNative),
     417           0 :         SYMBOL(GetProcAddress),
     418           0 :         SYMBOL(SwapBuffers),
     419           0 :         SYMBOL(CopyBuffers),
     420           0 :         SYMBOL(QueryString),
     421           0 :         SYMBOL(QueryContext),
     422           0 :         SYMBOL(BindTexImage),
     423           0 :         SYMBOL(ReleaseTexImage),
     424           0 :         SYMBOL(QuerySurface),
     425             :         END_OF_SYMBOLS
     426           0 :     };
     427             : 
     428           0 :     if (!GLLibraryLoader::LoadSymbols(mEGLLibrary, earlySymbols)) {
     429           0 :         NS_WARNING("Couldn't find required entry points in EGL library (early init)");
     430           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_SYM");
     431           0 :         return false;
     432             :     }
     433             : 
     434             :     {
     435           0 :         const char internalFuncName[] = "_Z35eglQueryStringImplementationANDROIDPvi";
     436           0 :         const auto& internalFunc = PR_FindFunctionSymbol(mEGLLibrary, internalFuncName);
     437           0 :         if (internalFunc) {
     438           0 :             *(PRFuncPtr*)&mSymbols.fQueryString = internalFunc;
     439             :         }
     440             :     }
     441             : 
     442           0 :     InitClientExtensions();
     443             : 
     444             :     const auto lookupFunction =
     445           0 :         (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
     446             : 
     447           0 :     const auto fnLoadSymbols = [&](const GLLibraryLoader::SymLoadStruct* symbols) {
     448           0 :         if (GLLibraryLoader::LoadSymbols(mEGLLibrary, symbols, lookupFunction))
     449           0 :             return true;
     450             : 
     451           0 :         ClearSymbols(symbols);
     452           0 :         return false;
     453           0 :     };
     454             : 
     455             :     // Check the ANGLE support the system has
     456           0 :     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     457           0 :     mIsANGLE = IsExtensionSupported(ANGLE_platform_angle);
     458             : 
     459           0 :     EGLDisplay chosenDisplay = nullptr;
     460             : 
     461             :     // Client exts are ready. (But not display exts!)
     462             : 
     463           0 :     if (mIsANGLE) {
     464           0 :         MOZ_ASSERT(IsExtensionSupported(ANGLE_platform_angle_d3d));
     465             :         const GLLibraryLoader::SymLoadStruct angleSymbols[] = {
     466           0 :             { (PRFuncPtr*)&mSymbols.fANGLEPlatformInitialize, { "ANGLEPlatformInitialize", nullptr } },
     467           0 :             { (PRFuncPtr*)&mSymbols.fANGLEPlatformShutdown, { "ANGLEPlatformShutdown", nullptr } },
     468           0 :             SYMBOL(GetPlatformDisplayEXT),
     469             :             END_OF_SYMBOLS
     470           0 :         };
     471           0 :         if (!fnLoadSymbols(angleSymbols)) {
     472           0 :             gfxCriticalError() << "Failed to load ANGLE symbols!";
     473           0 :             return false;
     474             :         }
     475             :     }
     476             : 
     477           0 :     if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
     478           0 :         nsCString accelAngleFailureId;
     479           0 :         bool accelAngleSupport = IsAccelAngleSupported(gfxInfo, &accelAngleFailureId);
     480           0 :         bool shouldTryAccel = forceAccel || accelAngleSupport;
     481           0 :         bool shouldTryWARP = !forceAccel; // Only if ANGLE not supported or fails
     482             : 
     483             :         // If WARP preferred, will override ANGLE support
     484           0 :         if (gfxPrefs::WebGLANGLEForceWARP()) {
     485           0 :             shouldTryWARP = true;
     486           0 :             shouldTryAccel = false;
     487           0 :             if (accelAngleFailureId.IsEmpty()) {
     488           0 :                 accelAngleFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_FORCE_WARP");
     489             :             }
     490             :         }
     491             : 
     492             :         // Hardware accelerated ANGLE path (supported or force accel)
     493           0 :         if (shouldTryAccel) {
     494           0 :             chosenDisplay = GetAndInitDisplayForAccelANGLE(*this, out_failureId);
     495             :         }
     496             : 
     497             :         // Report the acceleration status to telemetry
     498           0 :         if (!chosenDisplay) {
     499           0 :             if (accelAngleFailureId.IsEmpty()) {
     500           0 :                 Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
     501           0 :                                       NS_LITERAL_CSTRING("FEATURE_FAILURE_ACCL_ANGLE_UNKNOWN"));
     502             :             } else {
     503             :                 Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
     504           0 :                                       accelAngleFailureId);
     505             :             }
     506             :         } else {
     507           0 :             Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
     508           0 :                                   NS_LITERAL_CSTRING("SUCCESS"));
     509             :         }
     510             : 
     511             :         // Fallback to a WARP display if ANGLE fails, or if WARP is forced
     512           0 :         if (!chosenDisplay && shouldTryWARP) {
     513           0 :             chosenDisplay = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY);
     514           0 :             if (!chosenDisplay) {
     515           0 :                 if (out_failureId->IsEmpty()) {
     516           0 :                     *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WARP_FALLBACK");
     517             :                 }
     518           0 :                 NS_ERROR("Fallback WARP context failed to initialize.");
     519           0 :                 return false;
     520             :             }
     521           0 :             mIsWARP = true;
     522             :         }
     523             :     } else {
     524           0 :         chosenDisplay = GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY);
     525             :     }
     526             : 
     527           0 :     if (!chosenDisplay) {
     528           0 :         if (out_failureId->IsEmpty()) {
     529           0 :             *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_DISPLAY");
     530             :         }
     531           0 :         NS_WARNING("Failed to initialize a display.");
     532           0 :         return false;
     533             :     }
     534           0 :     mEGLDisplay = chosenDisplay;
     535             : 
     536           0 :     InitDisplayExtensions();
     537             : 
     538             :     ////////////////////////////////////
     539             :     // Alright, load display exts.
     540             : 
     541           0 :     if (IsExtensionSupported(KHR_lock_surface)) {
     542             :         const GLLibraryLoader::SymLoadStruct lockSymbols[] = {
     543           0 :             SYMBOL(LockSurfaceKHR),
     544           0 :             SYMBOL(UnlockSurfaceKHR),
     545             :             END_OF_SYMBOLS
     546           0 :         };
     547           0 :         if (!fnLoadSymbols(lockSymbols)) {
     548           0 :             NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");
     549           0 :             MarkExtensionUnsupported(KHR_lock_surface);
     550             :         }
     551             :     }
     552             : 
     553           0 :     if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
     554             :         const GLLibraryLoader::SymLoadStruct d3dSymbols[] = {
     555           0 :             SYMBOL(QuerySurfacePointerANGLE),
     556             :             END_OF_SYMBOLS
     557           0 :         };
     558           0 :         if (!fnLoadSymbols(d3dSymbols)) {
     559           0 :             NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");
     560           0 :             MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);
     561             :         }
     562             :     }
     563             : 
     564           0 :     if (IsExtensionSupported(KHR_fence_sync)) {
     565             :         const GLLibraryLoader::SymLoadStruct syncSymbols[] = {
     566           0 :             SYMBOL(CreateSyncKHR),
     567           0 :             SYMBOL(DestroySyncKHR),
     568           0 :             SYMBOL(ClientWaitSyncKHR),
     569           0 :             SYMBOL(GetSyncAttribKHR),
     570             :             END_OF_SYMBOLS
     571           0 :         };
     572           0 :         if (!fnLoadSymbols(syncSymbols)) {
     573           0 :             NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");
     574           0 :             MarkExtensionUnsupported(KHR_fence_sync);
     575             :         }
     576             :     }
     577             : 
     578           0 :     if (IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base)) {
     579             :         const GLLibraryLoader::SymLoadStruct imageSymbols[] = {
     580           0 :             SYMBOL(CreateImageKHR),
     581           0 :             SYMBOL(DestroyImageKHR),
     582             :             END_OF_SYMBOLS
     583           0 :         };
     584           0 :         if (!fnLoadSymbols(imageSymbols)) {
     585           0 :             NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");
     586           0 :             MarkExtensionUnsupported(KHR_image);
     587           0 :             MarkExtensionUnsupported(KHR_image_base);
     588           0 :             MarkExtensionUnsupported(KHR_image_pixmap);
     589             :         }
     590             :     } else {
     591           0 :         MarkExtensionUnsupported(KHR_image_pixmap);
     592             :     }
     593             : 
     594           0 :     if (IsExtensionSupported(ANDROID_native_fence_sync)) {
     595             :         const GLLibraryLoader::SymLoadStruct nativeFenceSymbols[] = {
     596           0 :             SYMBOL(DupNativeFenceFDANDROID),
     597             :             END_OF_SYMBOLS
     598           0 :         };
     599           0 :         if (!fnLoadSymbols(nativeFenceSymbols)) {
     600           0 :             NS_ERROR("EGL supports ANDROID_native_fence_sync without exposing its functions!");
     601           0 :             MarkExtensionUnsupported(ANDROID_native_fence_sync);
     602             :         }
     603             :     }
     604             : 
     605           0 :     if (IsExtensionSupported(KHR_stream)) {
     606             :         const GLLibraryLoader::SymLoadStruct streamSymbols[] = {
     607           0 :             SYMBOL(CreateStreamKHR),
     608           0 :             SYMBOL(DestroyStreamKHR),
     609           0 :             SYMBOL(QueryStreamKHR),
     610             :             END_OF_SYMBOLS
     611           0 :         };
     612           0 :         if (!fnLoadSymbols(streamSymbols)) {
     613           0 :             NS_ERROR("EGL supports KHR_stream without exposing its functions!");
     614           0 :             MarkExtensionUnsupported(KHR_stream);
     615             :         }
     616             :     }
     617             : 
     618           0 :     if (IsExtensionSupported(KHR_stream_consumer_gltexture)) {
     619             :         const GLLibraryLoader::SymLoadStruct streamConsumerSymbols[] = {
     620           0 :             SYMBOL(StreamConsumerAcquireKHR),
     621           0 :             SYMBOL(StreamConsumerReleaseKHR),
     622             :             END_OF_SYMBOLS
     623           0 :         };
     624           0 :         if (!fnLoadSymbols(streamConsumerSymbols)) {
     625           0 :             NS_ERROR("EGL supports KHR_stream_consumer_gltexture without exposing its functions!");
     626           0 :             MarkExtensionUnsupported(KHR_stream_consumer_gltexture);
     627             :         }
     628             :     }
     629             : 
     630           0 :     if (IsExtensionSupported(EXT_device_base)) {
     631             :         const GLLibraryLoader::SymLoadStruct deviceBaseSymbols[] = {
     632           0 :             SYMBOL(QueryDisplayAttribEXT),
     633             :             END_OF_SYMBOLS
     634           0 :         };
     635           0 :         if (!fnLoadSymbols(deviceBaseSymbols)) {
     636           0 :             NS_ERROR("EGL supports EXT_device_base without exposing its functions!");
     637           0 :             MarkExtensionUnsupported(EXT_device_base);
     638             :         }
     639             :     }
     640             : 
     641           0 :     if (IsExtensionSupported(EXT_device_query)) {
     642             :         const GLLibraryLoader::SymLoadStruct queryDisplaySymbols[] = {
     643           0 :             SYMBOL(QueryDeviceAttribEXT),
     644             :             END_OF_SYMBOLS
     645           0 :         };
     646           0 :         if (!fnLoadSymbols(queryDisplaySymbols)) {
     647           0 :             NS_ERROR("EGL supports EXT_device_query without exposing its functions!");
     648           0 :             MarkExtensionUnsupported(EXT_device_query);
     649             :         }
     650             :     }
     651             : 
     652           0 :     if (IsExtensionSupported(NV_stream_consumer_gltexture_yuv)) {
     653             :         const GLLibraryLoader::SymLoadStruct nvStreamSymbols[] = {
     654           0 :             SYMBOL(StreamConsumerGLTextureExternalAttribsNV),
     655             :             END_OF_SYMBOLS
     656           0 :         };
     657           0 :         if (!fnLoadSymbols(nvStreamSymbols)) {
     658           0 :             NS_ERROR("EGL supports NV_stream_consumer_gltexture_yuv without exposing its functions!");
     659           0 :             MarkExtensionUnsupported(NV_stream_consumer_gltexture_yuv);
     660             :         }
     661             :     }
     662             : 
     663           0 :     if (IsExtensionSupported(ANGLE_stream_producer_d3d_texture_nv12)) {
     664             :         const GLLibraryLoader::SymLoadStruct nvStreamSymbols[] = {
     665           0 :             SYMBOL(CreateStreamProducerD3DTextureNV12ANGLE),
     666           0 :             SYMBOL(StreamPostD3DTextureNV12ANGLE),
     667             :             END_OF_SYMBOLS
     668           0 :         };
     669           0 :         if (!fnLoadSymbols(nvStreamSymbols)) {
     670           0 :             NS_ERROR("EGL supports ANGLE_stream_producer_d3d_texture_nv12 without exposing its functions!");
     671           0 :             MarkExtensionUnsupported(ANGLE_stream_producer_d3d_texture_nv12);
     672             :         }
     673             :     }
     674             : 
     675           0 :     mInitialized = true;
     676           0 :     reporter.SetSuccessful();
     677           0 :     return true;
     678             : }
     679             : 
     680             : #undef SYMBOL
     681             : #undef END_OF_SYMBOLS
     682             : 
     683             : template<size_t N>
     684             : static void
     685           0 : MarkExtensions(const char* rawExtString, bool shouldDumpExts, const char* extType,
     686             :                std::bitset<N>* const out)
     687             : {
     688           0 :     MOZ_ASSERT(rawExtString);
     689             : 
     690           0 :     const nsDependentCString extString(rawExtString);
     691             : 
     692           0 :     std::vector<nsCString> extList;
     693           0 :     SplitByChar(extString, ' ', &extList);
     694             : 
     695           0 :     if (shouldDumpExts) {
     696           0 :         printf_stderr("%u EGL %s extensions: (*: recognized)\n",
     697           0 :                       (uint32_t)extList.size(), extType);
     698             :     }
     699             : 
     700           0 :     MarkBitfieldByStrings(extList, shouldDumpExts, sEGLExtensionNames, out);
     701           0 : }
     702             : 
     703             : void
     704           0 : GLLibraryEGL::InitClientExtensions()
     705             : {
     706           0 :     const bool shouldDumpExts = GLContext::ShouldDumpExts();
     707             : 
     708           0 :     const char* rawExtString = nullptr;
     709             : 
     710             : #ifndef ANDROID
     711             :     // Bug 1209612: Crashes on a number of android drivers.
     712             :     // Ideally we would only blocklist this there, but for now we don't need the client
     713             :     // extension list on ANDROID (we mostly need it on ANGLE), and we'd rather not crash.
     714           0 :     rawExtString = (const char*)fQueryString(nullptr, LOCAL_EGL_EXTENSIONS);
     715             : #endif
     716             : 
     717           0 :     if (!rawExtString) {
     718           0 :         if (shouldDumpExts) {
     719           0 :             printf_stderr("No EGL client extensions.\n");
     720             :         }
     721           0 :         return;
     722             :     }
     723             : 
     724           0 :     MarkExtensions(rawExtString, shouldDumpExts, "client", &mAvailableExtensions);
     725             : }
     726             : 
     727             : void
     728           0 : GLLibraryEGL::InitDisplayExtensions()
     729             : {
     730           0 :     MOZ_ASSERT(mEGLDisplay);
     731             : 
     732           0 :     const bool shouldDumpExts = GLContext::ShouldDumpExts();
     733             : 
     734           0 :     const auto rawExtString = (const char*)fQueryString(mEGLDisplay,
     735           0 :                                                         LOCAL_EGL_EXTENSIONS);
     736           0 :     if (!rawExtString) {
     737           0 :         NS_WARNING("Failed to query EGL display extensions!.");
     738           0 :         return;
     739             :     }
     740             : 
     741           0 :     MarkExtensions(rawExtString, shouldDumpExts, "display", &mAvailableExtensions);
     742             : }
     743             : 
     744             : void
     745           0 : GLLibraryEGL::DumpEGLConfig(EGLConfig cfg)
     746             : {
     747             :     int attrval;
     748             :     int err;
     749             : 
     750             : #define ATTR(_x) do {                                                   \
     751             :         fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval);  \
     752             :         if ((err = fGetError()) != 0x3000) {                        \
     753             :             printf_stderr("  %s: ERROR (0x%04x)\n", #_x, err);        \
     754             :         } else {                                                    \
     755             :             printf_stderr("  %s: %d (0x%04x)\n", #_x, attrval, attrval); \
     756             :         }                                                           \
     757             :     } while(0)
     758             : 
     759           0 :     printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
     760             : 
     761           0 :     ATTR(BUFFER_SIZE);
     762           0 :     ATTR(ALPHA_SIZE);
     763           0 :     ATTR(BLUE_SIZE);
     764           0 :     ATTR(GREEN_SIZE);
     765           0 :     ATTR(RED_SIZE);
     766           0 :     ATTR(DEPTH_SIZE);
     767           0 :     ATTR(STENCIL_SIZE);
     768           0 :     ATTR(CONFIG_CAVEAT);
     769           0 :     ATTR(CONFIG_ID);
     770           0 :     ATTR(LEVEL);
     771           0 :     ATTR(MAX_PBUFFER_HEIGHT);
     772           0 :     ATTR(MAX_PBUFFER_PIXELS);
     773           0 :     ATTR(MAX_PBUFFER_WIDTH);
     774           0 :     ATTR(NATIVE_RENDERABLE);
     775           0 :     ATTR(NATIVE_VISUAL_ID);
     776           0 :     ATTR(NATIVE_VISUAL_TYPE);
     777           0 :     ATTR(PRESERVED_RESOURCES);
     778           0 :     ATTR(SAMPLES);
     779           0 :     ATTR(SAMPLE_BUFFERS);
     780           0 :     ATTR(SURFACE_TYPE);
     781           0 :     ATTR(TRANSPARENT_TYPE);
     782           0 :     ATTR(TRANSPARENT_RED_VALUE);
     783           0 :     ATTR(TRANSPARENT_GREEN_VALUE);
     784           0 :     ATTR(TRANSPARENT_BLUE_VALUE);
     785           0 :     ATTR(BIND_TO_TEXTURE_RGB);
     786           0 :     ATTR(BIND_TO_TEXTURE_RGBA);
     787           0 :     ATTR(MIN_SWAP_INTERVAL);
     788           0 :     ATTR(MAX_SWAP_INTERVAL);
     789           0 :     ATTR(LUMINANCE_SIZE);
     790           0 :     ATTR(ALPHA_MASK_SIZE);
     791           0 :     ATTR(COLOR_BUFFER_TYPE);
     792           0 :     ATTR(RENDERABLE_TYPE);
     793           0 :     ATTR(CONFORMANT);
     794             : 
     795             : #undef ATTR
     796           0 : }
     797             : 
     798             : void
     799           0 : GLLibraryEGL::DumpEGLConfigs()
     800             : {
     801           0 :     int nc = 0;
     802           0 :     fGetConfigs(mEGLDisplay, nullptr, 0, &nc);
     803           0 :     EGLConfig* ec = new EGLConfig[nc];
     804           0 :     fGetConfigs(mEGLDisplay, ec, nc, &nc);
     805             : 
     806           0 :     for (int i = 0; i < nc; ++i) {
     807           0 :         printf_stderr("========= EGL Config %d ========\n", i);
     808           0 :         DumpEGLConfig(ec[i]);
     809             :     }
     810             : 
     811           0 :     delete [] ec;
     812           0 : }
     813             : 
     814             : static bool
     815           0 : ShouldTrace()
     816             : {
     817           0 :     static bool ret = gfxEnv::GlDebugVerbose();
     818           0 :     return ret;
     819             : }
     820             : 
     821             : void
     822           0 : BeforeEGLCall(const char* glFunction)
     823             : {
     824           0 :     if (ShouldTrace()) {
     825           0 :         printf_stderr("[egl] > %s\n", glFunction);
     826             :     }
     827           0 : }
     828             : 
     829             : void
     830           0 : AfterEGLCall(const char* glFunction)
     831             : {
     832           0 :     if (ShouldTrace()) {
     833           0 :         printf_stderr("[egl] < %s\n", glFunction);
     834             :     }
     835           0 : }
     836             : 
     837             : } /* namespace gl */
     838             : } /* namespace mozilla */
     839             : 

Generated by: LCOV version 1.13