gfx/gl/GLLibraryEGL.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/gl/GLLibraryEGL.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,425 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "GLLibraryEGL.h"
     1.9 +
    1.10 +#include "gfxCrashReporterUtils.h"
    1.11 +#include "mozilla/Preferences.h"
    1.12 +#include "nsDirectoryServiceDefs.h"
    1.13 +#include "nsDirectoryServiceUtils.h"
    1.14 +#include "nsPrintfCString.h"
    1.15 +#ifdef XP_WIN
    1.16 +#include "nsWindowsHelpers.h"
    1.17 +#endif
    1.18 +#include "prenv.h"
    1.19 +#include "GLContext.h"
    1.20 +#include "gfxPrefs.h"
    1.21 +
    1.22 +namespace mozilla {
    1.23 +namespace gl {
    1.24 +
    1.25 +GLLibraryEGL sEGLLibrary;
    1.26 +
    1.27 +// should match the order of EGLExtensions, and be null-terminated.
    1.28 +static const char *sEGLExtensionNames[] = {
    1.29 +    "EGL_KHR_image_base",
    1.30 +    "EGL_KHR_image_pixmap",
    1.31 +    "EGL_KHR_gl_texture_2D_image",
    1.32 +    "EGL_KHR_lock_surface",
    1.33 +    "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
    1.34 +    "EGL_EXT_create_context_robustness",
    1.35 +    "EGL_KHR_image",
    1.36 +    "EGL_KHR_fence_sync",
    1.37 +    nullptr
    1.38 +};
    1.39 +
    1.40 +#if defined(ANDROID)
    1.41 +
    1.42 +static PRLibrary* LoadApitraceLibrary()
    1.43 +{
    1.44 +    if (!gfxPrefs::UseApitrace()) {
    1.45 +        return nullptr;
    1.46 +    }
    1.47 +
    1.48 +    static PRLibrary* sApitraceLibrary = nullptr;
    1.49 +
    1.50 +    if (sApitraceLibrary)
    1.51 +        return sApitraceLibrary;
    1.52 +
    1.53 +    nsCString logFile = Preferences::GetCString("gfx.apitrace.logfile");
    1.54 +
    1.55 +    if (logFile.IsEmpty()) {
    1.56 +        logFile = "firefox.trace";
    1.57 +    }
    1.58 +
    1.59 +    // The firefox process can't write to /data/local, but it can write
    1.60 +    // to $GRE_HOME/
    1.61 +    nsAutoCString logPath;
    1.62 +    logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get());
    1.63 +
    1.64 +    // apitrace uses the TRACE_FILE environment variable to determine where
    1.65 +    // to log trace output to
    1.66 +    printf_stderr("Logging GL tracing output to %s", logPath.get());
    1.67 +    setenv("TRACE_FILE", logPath.get(), false);
    1.68 +
    1.69 +    printf_stderr("Attempting load of %s\n", APITRACE_LIB);
    1.70 +
    1.71 +    sApitraceLibrary = PR_LoadLibrary(APITRACE_LIB);
    1.72 +
    1.73 +    return sApitraceLibrary;
    1.74 +}
    1.75 +
    1.76 +#endif // ANDROID
    1.77 +
    1.78 +#ifdef XP_WIN
    1.79 +// see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
    1.80 +static PRLibrary*
    1.81 +LoadLibraryForEGLOnWindows(const nsAString& filename)
    1.82 +{
    1.83 +    nsCOMPtr<nsIFile> file;
    1.84 +	nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
    1.85 +    if (NS_FAILED(rv))
    1.86 +        return nullptr;
    1.87 +
    1.88 +    file->Append(filename);
    1.89 +    PRLibrary* lib = nullptr;
    1.90 +    rv = file->Load(&lib);
    1.91 +    if (NS_FAILED(rv)) {
    1.92 +        nsPrintfCString msg("Failed to load %s - Expect EGL initialization to fail",
    1.93 +                            NS_LossyConvertUTF16toASCII(filename).get());
    1.94 +        NS_WARNING(msg.get());
    1.95 +    }
    1.96 +    return lib;
    1.97 +}
    1.98 +#endif // XP_WIN
    1.99 +
   1.100 +bool
   1.101 +GLLibraryEGL::EnsureInitialized()
   1.102 +{
   1.103 +    if (mInitialized) {
   1.104 +        return true;
   1.105 +    }
   1.106 +
   1.107 +    mozilla::ScopedGfxFeatureReporter reporter("EGL");
   1.108 +
   1.109 +#ifdef XP_WIN
   1.110 +#ifdef MOZ_WEBGL
   1.111 +    if (!mEGLLibrary) {
   1.112 +        // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and
   1.113 +        // we should look for them there. We have to load the libs in this
   1.114 +        // order, because libEGL.dll depends on libGLESv2.dll which depends on the DXSDK
   1.115 +        // libraries. This matters especially for WebRT apps which are in a different directory.
   1.116 +        // See bug 760323 and bug 749459
   1.117 +
   1.118 +#ifndef MOZ_D3DCOMPILER_DLL
   1.119 +#error MOZ_D3DCOMPILER_DLL should have been defined by the Makefile
   1.120 +#endif
   1.121 +        // Windows 8.1 has d3dcompiler_47.dll in the system directory.
   1.122 +        // Try it first. Note that _46 will never be in the system
   1.123 +        // directory and we ship with at least _43. So there is no point
   1.124 +        // trying _46 and _43 in the system directory.
   1.125 +        if (!LoadLibrarySystem32(L"d3dcompiler_47.dll")) {
   1.126 +            // Fall back to the version that we shipped with.
   1.127 +            LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_DLL)));
   1.128 +        }
   1.129 +        // intentionally leak the D3DCOMPILER_DLL library
   1.130 +
   1.131 +        LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
   1.132 +        // intentionally leak the libGLESv2.dll library
   1.133 +
   1.134 +        mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
   1.135 +
   1.136 +        if (!mEGLLibrary)
   1.137 +            return false;
   1.138 +    }
   1.139 +#endif // MOZ_WEBGL
   1.140 +#else // !Windows
   1.141 +
   1.142 +    // On non-Windows (Android) we use system copies of libEGL. We look for
   1.143 +    // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
   1.144 +
   1.145 +#if defined(ANDROID)
   1.146 +    if (!mEGLLibrary)
   1.147 +        mEGLLibrary = LoadApitraceLibrary();
   1.148 +#endif
   1.149 +
   1.150 +    if (!mEGLLibrary) {
   1.151 +        printf_stderr("Attempting load of libEGL.so\n");
   1.152 +        mEGLLibrary = PR_LoadLibrary("libEGL.so");
   1.153 +    }
   1.154 +#if defined(XP_UNIX)
   1.155 +    if (!mEGLLibrary) {
   1.156 +        mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
   1.157 +    }
   1.158 +#endif
   1.159 +
   1.160 +    if (!mEGLLibrary) {
   1.161 +        NS_WARNING("Couldn't load EGL LIB.");
   1.162 +        return false;
   1.163 +    }
   1.164 +
   1.165 +#endif // !Windows
   1.166 +
   1.167 +#define SYMBOL(name) \
   1.168 +{ (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }
   1.169 +
   1.170 +    GLLibraryLoader::SymLoadStruct earlySymbols[] = {
   1.171 +        SYMBOL(GetDisplay),
   1.172 +        SYMBOL(GetCurrentSurface),
   1.173 +        SYMBOL(GetCurrentContext),
   1.174 +        SYMBOL(MakeCurrent),
   1.175 +        SYMBOL(DestroyContext),
   1.176 +        SYMBOL(CreateContext),
   1.177 +        SYMBOL(DestroySurface),
   1.178 +        SYMBOL(CreateWindowSurface),
   1.179 +        SYMBOL(CreatePbufferSurface),
   1.180 +        SYMBOL(CreatePixmapSurface),
   1.181 +        SYMBOL(BindAPI),
   1.182 +        SYMBOL(Initialize),
   1.183 +        SYMBOL(ChooseConfig),
   1.184 +        SYMBOL(GetError),
   1.185 +        SYMBOL(GetConfigs),
   1.186 +        SYMBOL(GetConfigAttrib),
   1.187 +        SYMBOL(WaitNative),
   1.188 +        SYMBOL(GetProcAddress),
   1.189 +        SYMBOL(SwapBuffers),
   1.190 +        SYMBOL(CopyBuffers),
   1.191 +        SYMBOL(QueryString),
   1.192 +        SYMBOL(QueryContext),
   1.193 +        SYMBOL(BindTexImage),
   1.194 +        SYMBOL(ReleaseTexImage),
   1.195 +        SYMBOL(QuerySurface),
   1.196 +        { nullptr, { nullptr } }
   1.197 +    };
   1.198 +
   1.199 +    if (!GLLibraryLoader::LoadSymbols(mEGLLibrary, &earlySymbols[0])) {
   1.200 +        NS_WARNING("Couldn't find required entry points in EGL library (early init)");
   1.201 +        return false;
   1.202 +    }
   1.203 +
   1.204 +    mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
   1.205 +    if (!fInitialize(mEGLDisplay, nullptr, nullptr))
   1.206 +        return false;
   1.207 +
   1.208 +    const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
   1.209 +    if (vendor && (strstr(vendor, "TransGaming") != 0 || strstr(vendor, "Google Inc.") != 0)) {
   1.210 +        mIsANGLE = true;
   1.211 +    }
   1.212 +    
   1.213 +    InitExtensions();
   1.214 +
   1.215 +    GLLibraryLoader::PlatformLookupFunction lookupFunction =
   1.216 +            (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
   1.217 +
   1.218 +    if (IsExtensionSupported(KHR_lock_surface)) {
   1.219 +        GLLibraryLoader::SymLoadStruct lockSymbols[] = {
   1.220 +            { (PRFuncPtr*) &mSymbols.fLockSurface,   { "eglLockSurfaceKHR",   nullptr } },
   1.221 +            { (PRFuncPtr*) &mSymbols.fUnlockSurface, { "eglUnlockSurfaceKHR", nullptr } },
   1.222 +            { nullptr, { nullptr } }
   1.223 +        };
   1.224 +
   1.225 +        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   1.226 +                                                    &lockSymbols[0],
   1.227 +                                                    lookupFunction);
   1.228 +        if (!success) {
   1.229 +            NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");
   1.230 +
   1.231 +            MarkExtensionUnsupported(KHR_lock_surface);
   1.232 +
   1.233 +            mSymbols.fLockSurface = nullptr;
   1.234 +            mSymbols.fUnlockSurface = nullptr;
   1.235 +        }
   1.236 +    }
   1.237 +
   1.238 +    if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
   1.239 +        GLLibraryLoader::SymLoadStruct d3dSymbols[] = {
   1.240 +            { (PRFuncPtr*) &mSymbols.fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", nullptr } },
   1.241 +            { nullptr, { nullptr } }
   1.242 +        };
   1.243 +
   1.244 +        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   1.245 +                                                    &d3dSymbols[0],
   1.246 +                                                    lookupFunction);
   1.247 +        if (!success) {
   1.248 +            NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");
   1.249 +
   1.250 +            MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);
   1.251 +
   1.252 +            mSymbols.fQuerySurfacePointerANGLE = nullptr;
   1.253 +        }
   1.254 +    }
   1.255 +
   1.256 +    if (IsExtensionSupported(KHR_fence_sync)) {
   1.257 +        GLLibraryLoader::SymLoadStruct syncSymbols[] = {
   1.258 +            { (PRFuncPtr*) &mSymbols.fCreateSync,     { "eglCreateSyncKHR",     nullptr } },
   1.259 +            { (PRFuncPtr*) &mSymbols.fDestroySync,    { "eglDestroySyncKHR",    nullptr } },
   1.260 +            { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "eglClientWaitSyncKHR", nullptr } },
   1.261 +            { (PRFuncPtr*) &mSymbols.fGetSyncAttrib,  { "eglGetSyncAttribKHR",  nullptr } },
   1.262 +            { nullptr, { nullptr } }
   1.263 +        };
   1.264 +
   1.265 +        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   1.266 +                                                    &syncSymbols[0],
   1.267 +                                                    lookupFunction);
   1.268 +        if (!success) {
   1.269 +            NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");
   1.270 +
   1.271 +            MarkExtensionUnsupported(KHR_fence_sync);
   1.272 +
   1.273 +            mSymbols.fCreateSync = nullptr;
   1.274 +            mSymbols.fDestroySync = nullptr;
   1.275 +            mSymbols.fClientWaitSync = nullptr;
   1.276 +            mSymbols.fGetSyncAttrib = nullptr;
   1.277 +        }
   1.278 +    }
   1.279 +
   1.280 +    if (IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base)) {
   1.281 +        GLLibraryLoader::SymLoadStruct imageSymbols[] = {
   1.282 +            { (PRFuncPtr*) &mSymbols.fCreateImage,  { "eglCreateImageKHR",  nullptr } },
   1.283 +            { (PRFuncPtr*) &mSymbols.fDestroyImage, { "eglDestroyImageKHR", nullptr } },
   1.284 +            { nullptr, { nullptr } }
   1.285 +        };
   1.286 +
   1.287 +        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
   1.288 +                                                    &imageSymbols[0],
   1.289 +                                                    lookupFunction);
   1.290 +        if (!success) {
   1.291 +            NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");
   1.292 +
   1.293 +            MarkExtensionUnsupported(KHR_image);
   1.294 +            MarkExtensionUnsupported(KHR_image_base);
   1.295 +            MarkExtensionUnsupported(KHR_image_pixmap);
   1.296 +
   1.297 +            mSymbols.fCreateImage = nullptr;
   1.298 +            mSymbols.fDestroyImage = nullptr;
   1.299 +        }
   1.300 +    } else {
   1.301 +        MarkExtensionUnsupported(KHR_image_pixmap);
   1.302 +    }
   1.303 +
   1.304 +    mInitialized = true;
   1.305 +    reporter.SetSuccessful();
   1.306 +    return true;
   1.307 +}
   1.308 +
   1.309 +void
   1.310 +GLLibraryEGL::InitExtensions()
   1.311 +{
   1.312 +    const char *extensions = (const char*)fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
   1.313 +
   1.314 +    if (!extensions) {
   1.315 +        NS_WARNING("Failed to load EGL extension list!");
   1.316 +        return;
   1.317 +    }
   1.318 +
   1.319 +    bool debugMode = false;
   1.320 +#ifdef DEBUG
   1.321 +    if (PR_GetEnv("MOZ_GL_DEBUG"))
   1.322 +        debugMode = true;
   1.323 +
   1.324 +    static bool firstRun = true;
   1.325 +#else
   1.326 +    // Non-DEBUG, so never spew.
   1.327 +    const bool firstRun = false;
   1.328 +#endif
   1.329 +
   1.330 +    GLContext::InitializeExtensionsBitSet(mAvailableExtensions, extensions, sEGLExtensionNames, firstRun && debugMode);
   1.331 +
   1.332 +#ifdef DEBUG
   1.333 +    firstRun = false;
   1.334 +#endif
   1.335 +}
   1.336 +
   1.337 +void
   1.338 +GLLibraryEGL::DumpEGLConfig(EGLConfig cfg)
   1.339 +{
   1.340 +    int attrval;
   1.341 +    int err;
   1.342 +
   1.343 +#define ATTR(_x) do {                                                   \
   1.344 +        fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval);  \
   1.345 +        if ((err = fGetError()) != 0x3000) {                        \
   1.346 +            printf_stderr("  %s: ERROR (0x%04x)\n", #_x, err);        \
   1.347 +        } else {                                                    \
   1.348 +            printf_stderr("  %s: %d (0x%04x)\n", #_x, attrval, attrval); \
   1.349 +        }                                                           \
   1.350 +    } while(0)
   1.351 +
   1.352 +    printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
   1.353 +
   1.354 +    ATTR(BUFFER_SIZE);
   1.355 +    ATTR(ALPHA_SIZE);
   1.356 +    ATTR(BLUE_SIZE);
   1.357 +    ATTR(GREEN_SIZE);
   1.358 +    ATTR(RED_SIZE);
   1.359 +    ATTR(DEPTH_SIZE);
   1.360 +    ATTR(STENCIL_SIZE);
   1.361 +    ATTR(CONFIG_CAVEAT);
   1.362 +    ATTR(CONFIG_ID);
   1.363 +    ATTR(LEVEL);
   1.364 +    ATTR(MAX_PBUFFER_HEIGHT);
   1.365 +    ATTR(MAX_PBUFFER_PIXELS);
   1.366 +    ATTR(MAX_PBUFFER_WIDTH);
   1.367 +    ATTR(NATIVE_RENDERABLE);
   1.368 +    ATTR(NATIVE_VISUAL_ID);
   1.369 +    ATTR(NATIVE_VISUAL_TYPE);
   1.370 +    ATTR(PRESERVED_RESOURCES);
   1.371 +    ATTR(SAMPLES);
   1.372 +    ATTR(SAMPLE_BUFFERS);
   1.373 +    ATTR(SURFACE_TYPE);
   1.374 +    ATTR(TRANSPARENT_TYPE);
   1.375 +    ATTR(TRANSPARENT_RED_VALUE);
   1.376 +    ATTR(TRANSPARENT_GREEN_VALUE);
   1.377 +    ATTR(TRANSPARENT_BLUE_VALUE);
   1.378 +    ATTR(BIND_TO_TEXTURE_RGB);
   1.379 +    ATTR(BIND_TO_TEXTURE_RGBA);
   1.380 +    ATTR(MIN_SWAP_INTERVAL);
   1.381 +    ATTR(MAX_SWAP_INTERVAL);
   1.382 +    ATTR(LUMINANCE_SIZE);
   1.383 +    ATTR(ALPHA_MASK_SIZE);
   1.384 +    ATTR(COLOR_BUFFER_TYPE);
   1.385 +    ATTR(RENDERABLE_TYPE);
   1.386 +    ATTR(CONFORMANT);
   1.387 +
   1.388 +#undef ATTR
   1.389 +}
   1.390 +
   1.391 +void
   1.392 +GLLibraryEGL::DumpEGLConfigs()
   1.393 +{
   1.394 +    int nc = 0;
   1.395 +    fGetConfigs(mEGLDisplay, nullptr, 0, &nc);
   1.396 +    EGLConfig *ec = new EGLConfig[nc];
   1.397 +    fGetConfigs(mEGLDisplay, ec, nc, &nc);
   1.398 +
   1.399 +    for (int i = 0; i < nc; ++i) {
   1.400 +        printf_stderr ("========= EGL Config %d ========\n", i);
   1.401 +        DumpEGLConfig(ec[i]);
   1.402 +    }
   1.403 +
   1.404 +    delete [] ec;
   1.405 +}
   1.406 +
   1.407 +#ifdef DEBUG
   1.408 +/*static*/ void
   1.409 +GLLibraryEGL::BeforeGLCall(const char* glFunction)
   1.410 +{
   1.411 +    if (GLContext::DebugMode()) {
   1.412 +        if (GLContext::DebugMode() & GLContext::DebugTrace)
   1.413 +            printf_stderr("[egl] > %s\n", glFunction);
   1.414 +    }
   1.415 +}
   1.416 +
   1.417 +/*static*/ void
   1.418 +GLLibraryEGL::AfterGLCall(const char* glFunction)
   1.419 +{
   1.420 +    if (GLContext::DebugMode() & GLContext::DebugTrace) {
   1.421 +        printf_stderr("[egl] < %s\n", glFunction);
   1.422 +    }
   1.423 +}
   1.424 +#endif
   1.425 +
   1.426 +} /* namespace gl */
   1.427 +} /* namespace mozilla */
   1.428 +

mercurial