gfx/gl/GLLibraryEGL.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial