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 "mozilla/Assertions.h"
10 #include "nsDirectoryServiceDefs.h"
11 #include "nsDirectoryServiceUtils.h"
12 #include "nsPrintfCString.h"
14 #include "nsWindowsHelpers.h"
17 #include "GLContext.h"
23 GLLibraryEGL sEGLLibrary
;
25 ThreadLocal
<EGLContext
> GLLibraryEGL::sCurrentContext
;
28 // should match the order of EGLExtensions, and be null-terminated.
29 static const char *sEGLExtensionNames
[] = {
31 "EGL_KHR_image_pixmap",
32 "EGL_KHR_gl_texture_2D_image",
33 "EGL_KHR_lock_surface",
34 "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
35 "EGL_EXT_create_context_robustness",
38 "EGL_ANDROID_native_fence_sync",
39 "EGL_ANDROID_image_crop",
45 static PRLibrary
* LoadApitraceLibrary()
47 if (!gfxPrefs::UseApitrace()) {
51 static PRLibrary
* sApitraceLibrary
= nullptr;
54 return sApitraceLibrary
;
56 nsCString logFile
= Preferences::GetCString("gfx.apitrace.logfile");
58 if (logFile
.IsEmpty()) {
59 logFile
= "firefox.trace";
62 // The firefox process can't write to /data/local, but it can write
64 nsAutoCString logPath
;
65 logPath
.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile
.get());
67 // apitrace uses the TRACE_FILE environment variable to determine where
68 // to log trace output to
69 printf_stderr("Logging GL tracing output to %s", logPath
.get());
70 setenv("TRACE_FILE", logPath
.get(), false);
72 printf_stderr("Attempting load of %s\n", APITRACE_LIB
);
74 sApitraceLibrary
= PR_LoadLibrary(APITRACE_LIB
);
76 return sApitraceLibrary
;
82 // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
84 LoadLibraryForEGLOnWindows(const nsAString
& filename
)
86 nsCOMPtr
<nsIFile
> file
;
87 nsresult rv
= NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(file
));
91 file
->Append(filename
);
92 PRLibrary
* lib
= nullptr;
93 rv
= file
->Load(&lib
);
95 nsPrintfCString
msg("Failed to load %s - Expect EGL initialization to fail",
96 NS_LossyConvertUTF16toASCII(filename
).get());
97 NS_WARNING(msg
.get());
104 GetAndInitDisplay(GLLibraryEGL
& egl
, void* displayType
)
106 EGLDisplay display
= egl
.fGetDisplay(displayType
);
107 if (display
== EGL_NO_DISPLAY
)
108 return EGL_NO_DISPLAY
;
110 if (!egl
.fInitialize(display
, nullptr, nullptr))
111 return EGL_NO_DISPLAY
;
117 GLLibraryEGL::EnsureInitialized()
123 mozilla::ScopedGfxFeatureReporter
reporter("EGL");
126 if (!sCurrentContext
.init())
127 MOZ_CRASH("Tls init failed");
132 // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and
133 // we should look for them there. We have to load the libs in this
134 // order, because libEGL.dll depends on libGLESv2.dll which depends on the DXSDK
135 // libraries. This matters especially for WebRT apps which are in a different directory.
136 // See bug 760323 and bug 749459
138 // Also note that we intentionally leak the libs we load.
141 // Windows 8.1 has d3dcompiler_47.dll in the system directory.
142 // Try it first. Note that _46 will never be in the system
143 // directory and we ship with at least _43. So there is no point
144 // trying _46 and _43 in the system directory.
146 if (LoadLibrarySystem32(L
"d3dcompiler_47.dll"))
149 #ifdef MOZ_D3DCOMPILER_VISTA_DLL
150 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL
))))
154 #ifdef MOZ_D3DCOMPILER_XP_DLL
155 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_XP_DLL
))))
159 MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
162 LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
164 mEGLLibrary
= LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
172 // On non-Windows (Android) we use system copies of libEGL. We look for
173 // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
177 mEGLLibrary
= LoadApitraceLibrary();
181 printf_stderr("Attempting load of libEGL.so\n");
182 mEGLLibrary
= PR_LoadLibrary("libEGL.so");
186 mEGLLibrary
= PR_LoadLibrary("libEGL.so.1");
191 NS_WARNING("Couldn't load EGL LIB.");
197 #define SYMBOL(name) \
198 { (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }
200 GLLibraryLoader::SymLoadStruct earlySymbols
[] = {
203 SYMBOL(GetCurrentSurface
),
204 SYMBOL(GetCurrentContext
),
206 SYMBOL(DestroyContext
),
207 SYMBOL(CreateContext
),
208 SYMBOL(DestroySurface
),
209 SYMBOL(CreateWindowSurface
),
210 SYMBOL(CreatePbufferSurface
),
211 SYMBOL(CreatePixmapSurface
),
214 SYMBOL(ChooseConfig
),
217 SYMBOL(GetConfigAttrib
),
219 SYMBOL(GetProcAddress
),
223 SYMBOL(QueryContext
),
224 SYMBOL(BindTexImage
),
225 SYMBOL(ReleaseTexImage
),
226 SYMBOL(QuerySurface
),
227 { nullptr, { nullptr } }
230 if (!GLLibraryLoader::LoadSymbols(mEGLLibrary
, &earlySymbols
[0])) {
231 NS_WARNING("Couldn't find required entry points in EGL library (early init)");
235 GLLibraryLoader::SymLoadStruct optionalSymbols
[] = {
236 // On Android 4.3 and up, certain features like ANDROID_native_fence_sync
237 // can only be queried by using a special eglQueryString.
238 { (PRFuncPtr
*) &mSymbols
.fQueryStringImplementationANDROID
,
239 { "_Z35eglQueryStringImplementationANDROIDPvi", nullptr } },
240 { nullptr, { nullptr } }
243 // Do not warn about the failure to load this - see bug 1092191
244 GLLibraryLoader::LoadSymbols(mEGLLibrary
, &optionalSymbols
[0],
245 nullptr, nullptr, false);
247 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
248 MOZ_RELEASE_ASSERT(mSymbols
.fQueryStringImplementationANDROID
,
249 "Couldn't find eglQueryStringImplementationANDROID");
252 mEGLDisplay
= GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY
);
254 const char* vendor
= (char*)fQueryString(mEGLDisplay
, LOCAL_EGL_VENDOR
);
255 if (vendor
&& (strstr(vendor
, "TransGaming") != 0 ||
256 strstr(vendor
, "Google Inc.") != 0))
262 EGLDisplay newDisplay
= EGL_NO_DISPLAY
;
264 // D3D11 ANGLE only works with OMTC; there's a bug in the non-OMTC layer
265 // manager, and it's pointless to try to fix it. We also don't try
266 // D3D11 ANGLE if the layer manager is prefering D3D9 (hrm, do we care?)
267 if (gfxPrefs::LayersOffMainThreadCompositionEnabled() &&
268 !gfxPrefs::LayersPreferD3D9())
270 if (gfxPrefs::WebGLANGLEForceD3D11()) {
271 newDisplay
= GetAndInitDisplay(*this,
272 LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE
);
273 } else if (gfxPrefs::WebGLANGLETryD3D11()) {
274 newDisplay
= GetAndInitDisplay(*this,
275 LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE
);
279 if (newDisplay
!= EGL_NO_DISPLAY
) {
280 DebugOnly
<EGLBoolean
> success
= fTerminate(mEGLDisplay
);
281 MOZ_ASSERT(success
== LOCAL_EGL_TRUE
);
283 mEGLDisplay
= newDisplay
;
285 vendor
= (char*)fQueryString(mEGLDisplay
, LOCAL_EGL_VENDOR
);
291 GLLibraryLoader::PlatformLookupFunction lookupFunction
=
292 (GLLibraryLoader::PlatformLookupFunction
)mSymbols
.fGetProcAddress
;
294 if (IsExtensionSupported(KHR_lock_surface
)) {
295 GLLibraryLoader::SymLoadStruct lockSymbols
[] = {
296 { (PRFuncPtr
*) &mSymbols
.fLockSurface
, { "eglLockSurfaceKHR", nullptr } },
297 { (PRFuncPtr
*) &mSymbols
.fUnlockSurface
, { "eglUnlockSurfaceKHR", nullptr } },
298 { nullptr, { nullptr } }
301 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
305 NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");
307 MarkExtensionUnsupported(KHR_lock_surface
);
309 mSymbols
.fLockSurface
= nullptr;
310 mSymbols
.fUnlockSurface
= nullptr;
314 if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle
)) {
315 GLLibraryLoader::SymLoadStruct d3dSymbols
[] = {
316 { (PRFuncPtr
*) &mSymbols
.fQuerySurfacePointerANGLE
, { "eglQuerySurfacePointerANGLE", nullptr } },
317 { nullptr, { nullptr } }
320 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
324 NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");
326 MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle
);
328 mSymbols
.fQuerySurfacePointerANGLE
= nullptr;
332 //XXX: use correct extension name
333 if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle
)) {
334 GLLibraryLoader::SymLoadStruct d3dSymbols
[] = {
335 { (PRFuncPtr
*)&mSymbols
.fSurfaceReleaseSyncANGLE
, { "eglSurfaceReleaseSyncANGLE", nullptr } },
336 { nullptr, { nullptr } }
339 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
343 NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");
345 MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle
);
347 mSymbols
.fSurfaceReleaseSyncANGLE
= nullptr;
351 if (IsExtensionSupported(KHR_fence_sync
)) {
352 GLLibraryLoader::SymLoadStruct syncSymbols
[] = {
353 { (PRFuncPtr
*) &mSymbols
.fCreateSync
, { "eglCreateSyncKHR", nullptr } },
354 { (PRFuncPtr
*) &mSymbols
.fDestroySync
, { "eglDestroySyncKHR", nullptr } },
355 { (PRFuncPtr
*) &mSymbols
.fClientWaitSync
, { "eglClientWaitSyncKHR", nullptr } },
356 { (PRFuncPtr
*) &mSymbols
.fGetSyncAttrib
, { "eglGetSyncAttribKHR", nullptr } },
357 { nullptr, { nullptr } }
360 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
364 NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");
366 MarkExtensionUnsupported(KHR_fence_sync
);
368 mSymbols
.fCreateSync
= nullptr;
369 mSymbols
.fDestroySync
= nullptr;
370 mSymbols
.fClientWaitSync
= nullptr;
371 mSymbols
.fGetSyncAttrib
= nullptr;
375 if (IsExtensionSupported(KHR_image
) || IsExtensionSupported(KHR_image_base
)) {
376 GLLibraryLoader::SymLoadStruct imageSymbols
[] = {
377 { (PRFuncPtr
*) &mSymbols
.fCreateImage
, { "eglCreateImageKHR", nullptr } },
378 { (PRFuncPtr
*) &mSymbols
.fDestroyImage
, { "eglDestroyImageKHR", nullptr } },
379 { nullptr, { nullptr } }
382 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
386 NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");
388 MarkExtensionUnsupported(KHR_image
);
389 MarkExtensionUnsupported(KHR_image_base
);
390 MarkExtensionUnsupported(KHR_image_pixmap
);
392 mSymbols
.fCreateImage
= nullptr;
393 mSymbols
.fDestroyImage
= nullptr;
396 MarkExtensionUnsupported(KHR_image_pixmap
);
399 if (IsExtensionSupported(ANDROID_native_fence_sync
)) {
400 GLLibraryLoader::SymLoadStruct nativeFenceSymbols
[] = {
401 { (PRFuncPtr
*) &mSymbols
.fDupNativeFenceFDANDROID
, { "eglDupNativeFenceFDANDROID", nullptr } },
402 { nullptr, { nullptr } }
405 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
406 &nativeFenceSymbols
[0],
409 NS_ERROR("EGL supports ANDROID_native_fence_sync without exposing its functions!");
411 MarkExtensionUnsupported(ANDROID_native_fence_sync
);
413 mSymbols
.fDupNativeFenceFDANDROID
= nullptr;
418 reporter
.SetSuccessful();
423 GLLibraryEGL::InitExtensions()
425 const char *extensions
= (const char*)fQueryString(mEGLDisplay
, LOCAL_EGL_EXTENSIONS
);
428 NS_WARNING("Failed to load EGL extension list!");
432 GLContext::InitializeExtensionsBitSet(mAvailableExtensions
, extensions
,
437 GLLibraryEGL::DumpEGLConfig(EGLConfig cfg
)
442 #define ATTR(_x) do { \
443 fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
444 if ((err = fGetError()) != 0x3000) { \
445 printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
447 printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
451 printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg
, cfg
);
463 ATTR(MAX_PBUFFER_HEIGHT
);
464 ATTR(MAX_PBUFFER_PIXELS
);
465 ATTR(MAX_PBUFFER_WIDTH
);
466 ATTR(NATIVE_RENDERABLE
);
467 ATTR(NATIVE_VISUAL_ID
);
468 ATTR(NATIVE_VISUAL_TYPE
);
469 ATTR(PRESERVED_RESOURCES
);
471 ATTR(SAMPLE_BUFFERS
);
473 ATTR(TRANSPARENT_TYPE
);
474 ATTR(TRANSPARENT_RED_VALUE
);
475 ATTR(TRANSPARENT_GREEN_VALUE
);
476 ATTR(TRANSPARENT_BLUE_VALUE
);
477 ATTR(BIND_TO_TEXTURE_RGB
);
478 ATTR(BIND_TO_TEXTURE_RGBA
);
479 ATTR(MIN_SWAP_INTERVAL
);
480 ATTR(MAX_SWAP_INTERVAL
);
481 ATTR(LUMINANCE_SIZE
);
482 ATTR(ALPHA_MASK_SIZE
);
483 ATTR(COLOR_BUFFER_TYPE
);
484 ATTR(RENDERABLE_TYPE
);
491 GLLibraryEGL::DumpEGLConfigs()
494 fGetConfigs(mEGLDisplay
, nullptr, 0, &nc
);
495 EGLConfig
*ec
= new EGLConfig
[nc
];
496 fGetConfigs(mEGLDisplay
, ec
, nc
, &nc
);
498 for (int i
= 0; i
< nc
; ++i
) {
499 printf_stderr ("========= EGL Config %d ========\n", i
);
500 DumpEGLConfig(ec
[i
]);
508 GLLibraryEGL::BeforeGLCall(const char* glFunction
)
510 if (GLContext::DebugMode()) {
511 if (GLContext::DebugMode() & GLContext::DebugTrace
)
512 printf_stderr("[egl] > %s\n", glFunction
);
517 GLLibraryEGL::AfterGLCall(const char* glFunction
)
519 if (GLContext::DebugMode() & GLContext::DebugTrace
) {
520 printf_stderr("[egl] < %s\n", glFunction
);
526 } /* namespace mozilla */