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",
44 static PRLibrary
* LoadApitraceLibrary()
46 if (!gfxPrefs::UseApitrace()) {
50 static PRLibrary
* sApitraceLibrary
= nullptr;
53 return sApitraceLibrary
;
55 nsCString logFile
= Preferences::GetCString("gfx.apitrace.logfile");
57 if (logFile
.IsEmpty()) {
58 logFile
= "firefox.trace";
61 // The firefox process can't write to /data/local, but it can write
63 nsAutoCString logPath
;
64 logPath
.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile
.get());
66 // apitrace uses the TRACE_FILE environment variable to determine where
67 // to log trace output to
68 printf_stderr("Logging GL tracing output to %s", logPath
.get());
69 setenv("TRACE_FILE", logPath
.get(), false);
71 printf_stderr("Attempting load of %s\n", APITRACE_LIB
);
73 sApitraceLibrary
= PR_LoadLibrary(APITRACE_LIB
);
75 return sApitraceLibrary
;
81 // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
83 LoadLibraryForEGLOnWindows(const nsAString
& filename
)
85 nsCOMPtr
<nsIFile
> file
;
86 nsresult rv
= NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(file
));
90 file
->Append(filename
);
91 PRLibrary
* lib
= nullptr;
92 rv
= file
->Load(&lib
);
94 nsPrintfCString
msg("Failed to load %s - Expect EGL initialization to fail",
95 NS_LossyConvertUTF16toASCII(filename
).get());
96 NS_WARNING(msg
.get());
103 GLLibraryEGL::EnsureInitialized()
109 mozilla::ScopedGfxFeatureReporter
reporter("EGL");
112 if (!sCurrentContext
.init())
113 MOZ_CRASH("Tls init failed");
118 // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and
119 // we should look for them there. We have to load the libs in this
120 // order, because libEGL.dll depends on libGLESv2.dll which depends on the DXSDK
121 // libraries. This matters especially for WebRT apps which are in a different directory.
122 // See bug 760323 and bug 749459
124 // Also note that we intentionally leak the libs we load.
127 // Windows 8.1 has d3dcompiler_47.dll in the system directory.
128 // Try it first. Note that _46 will never be in the system
129 // directory and we ship with at least _43. So there is no point
130 // trying _46 and _43 in the system directory.
132 if (LoadLibrarySystem32(L
"d3dcompiler_47.dll"))
135 #ifdef MOZ_D3DCOMPILER_VISTA_DLL
136 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL
))))
140 #ifdef MOZ_D3DCOMPILER_XP_DLL
141 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_XP_DLL
))))
145 MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
148 LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
150 mEGLLibrary
= LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
158 // On non-Windows (Android) we use system copies of libEGL. We look for
159 // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
163 mEGLLibrary
= LoadApitraceLibrary();
167 printf_stderr("Attempting load of libEGL.so\n");
168 mEGLLibrary
= PR_LoadLibrary("libEGL.so");
172 mEGLLibrary
= PR_LoadLibrary("libEGL.so.1");
177 NS_WARNING("Couldn't load EGL LIB.");
183 #define SYMBOL(name) \
184 { (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }
186 GLLibraryLoader::SymLoadStruct earlySymbols
[] = {
188 SYMBOL(GetCurrentSurface
),
189 SYMBOL(GetCurrentContext
),
191 SYMBOL(DestroyContext
),
192 SYMBOL(CreateContext
),
193 SYMBOL(DestroySurface
),
194 SYMBOL(CreateWindowSurface
),
195 SYMBOL(CreatePbufferSurface
),
196 SYMBOL(CreatePixmapSurface
),
199 SYMBOL(ChooseConfig
),
202 SYMBOL(GetConfigAttrib
),
204 SYMBOL(GetProcAddress
),
208 SYMBOL(QueryContext
),
209 SYMBOL(BindTexImage
),
210 SYMBOL(ReleaseTexImage
),
211 SYMBOL(QuerySurface
),
212 { nullptr, { nullptr } }
215 if (!GLLibraryLoader::LoadSymbols(mEGLLibrary
, &earlySymbols
[0])) {
216 NS_WARNING("Couldn't find required entry points in EGL library (early init)");
220 GLLibraryLoader::SymLoadStruct optionalSymbols
[] = {
221 // On Android 4.3 and up, certain features like ANDROID_native_fence_sync
222 // can only be queried by using a special eglQueryString.
223 { (PRFuncPtr
*) &mSymbols
.fQueryStringImplementationANDROID
,
224 { "_Z35eglQueryStringImplementationANDROIDPvi", nullptr } },
225 { nullptr, { nullptr } }
228 GLLibraryLoader::LoadSymbols(mEGLLibrary
, &optionalSymbols
[0]);
230 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
231 MOZ_RELEASE_ASSERT(mSymbols
.fQueryStringImplementationANDROID
,
232 "Couldn't find eglQueryStringImplementationANDROID");
235 mEGLDisplay
= fGetDisplay(EGL_DEFAULT_DISPLAY
);
236 if (!fInitialize(mEGLDisplay
, nullptr, nullptr))
239 const char *vendor
= (const char*) fQueryString(mEGLDisplay
, LOCAL_EGL_VENDOR
);
240 if (vendor
&& (strstr(vendor
, "TransGaming") != 0 || strstr(vendor
, "Google Inc.") != 0)) {
246 GLLibraryLoader::PlatformLookupFunction lookupFunction
=
247 (GLLibraryLoader::PlatformLookupFunction
)mSymbols
.fGetProcAddress
;
249 if (IsExtensionSupported(KHR_lock_surface
)) {
250 GLLibraryLoader::SymLoadStruct lockSymbols
[] = {
251 { (PRFuncPtr
*) &mSymbols
.fLockSurface
, { "eglLockSurfaceKHR", nullptr } },
252 { (PRFuncPtr
*) &mSymbols
.fUnlockSurface
, { "eglUnlockSurfaceKHR", nullptr } },
253 { nullptr, { nullptr } }
256 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
260 NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");
262 MarkExtensionUnsupported(KHR_lock_surface
);
264 mSymbols
.fLockSurface
= nullptr;
265 mSymbols
.fUnlockSurface
= nullptr;
269 if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle
)) {
270 GLLibraryLoader::SymLoadStruct d3dSymbols
[] = {
271 { (PRFuncPtr
*) &mSymbols
.fQuerySurfacePointerANGLE
, { "eglQuerySurfacePointerANGLE", nullptr } },
272 { nullptr, { nullptr } }
275 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
279 NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");
281 MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle
);
283 mSymbols
.fQuerySurfacePointerANGLE
= nullptr;
287 if (IsExtensionSupported(KHR_fence_sync
)) {
288 GLLibraryLoader::SymLoadStruct syncSymbols
[] = {
289 { (PRFuncPtr
*) &mSymbols
.fCreateSync
, { "eglCreateSyncKHR", nullptr } },
290 { (PRFuncPtr
*) &mSymbols
.fDestroySync
, { "eglDestroySyncKHR", nullptr } },
291 { (PRFuncPtr
*) &mSymbols
.fClientWaitSync
, { "eglClientWaitSyncKHR", nullptr } },
292 { (PRFuncPtr
*) &mSymbols
.fGetSyncAttrib
, { "eglGetSyncAttribKHR", nullptr } },
293 { nullptr, { nullptr } }
296 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
300 NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");
302 MarkExtensionUnsupported(KHR_fence_sync
);
304 mSymbols
.fCreateSync
= nullptr;
305 mSymbols
.fDestroySync
= nullptr;
306 mSymbols
.fClientWaitSync
= nullptr;
307 mSymbols
.fGetSyncAttrib
= nullptr;
311 if (IsExtensionSupported(KHR_image
) || IsExtensionSupported(KHR_image_base
)) {
312 GLLibraryLoader::SymLoadStruct imageSymbols
[] = {
313 { (PRFuncPtr
*) &mSymbols
.fCreateImage
, { "eglCreateImageKHR", nullptr } },
314 { (PRFuncPtr
*) &mSymbols
.fDestroyImage
, { "eglDestroyImageKHR", nullptr } },
315 { nullptr, { nullptr } }
318 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
322 NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");
324 MarkExtensionUnsupported(KHR_image
);
325 MarkExtensionUnsupported(KHR_image_base
);
326 MarkExtensionUnsupported(KHR_image_pixmap
);
328 mSymbols
.fCreateImage
= nullptr;
329 mSymbols
.fDestroyImage
= nullptr;
332 MarkExtensionUnsupported(KHR_image_pixmap
);
335 if (IsExtensionSupported(ANDROID_native_fence_sync
)) {
336 GLLibraryLoader::SymLoadStruct nativeFenceSymbols
[] = {
337 { (PRFuncPtr
*) &mSymbols
.fDupNativeFenceFDANDROID
, { "eglDupNativeFenceFDANDROID", nullptr } },
338 { nullptr, { nullptr } }
341 bool success
= GLLibraryLoader::LoadSymbols(mEGLLibrary
,
342 &nativeFenceSymbols
[0],
345 NS_ERROR("EGL supports ANDROID_native_fence_sync without exposing its functions!");
347 MarkExtensionUnsupported(ANDROID_native_fence_sync
);
349 mSymbols
.fDupNativeFenceFDANDROID
= nullptr;
354 reporter
.SetSuccessful();
359 GLLibraryEGL::InitExtensions()
361 const char *extensions
= (const char*)fQueryString(mEGLDisplay
, LOCAL_EGL_EXTENSIONS
);
364 NS_WARNING("Failed to load EGL extension list!");
368 bool debugMode
= false;
370 if (PR_GetEnv("MOZ_GL_DEBUG"))
373 static bool firstRun
= true;
375 // Non-DEBUG, so never spew.
376 const bool firstRun
= false;
379 GLContext::InitializeExtensionsBitSet(mAvailableExtensions
, extensions
, sEGLExtensionNames
, firstRun
&& debugMode
);
387 GLLibraryEGL::DumpEGLConfig(EGLConfig cfg
)
392 #define ATTR(_x) do { \
393 fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
394 if ((err = fGetError()) != 0x3000) { \
395 printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
397 printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
401 printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg
, cfg
);
413 ATTR(MAX_PBUFFER_HEIGHT
);
414 ATTR(MAX_PBUFFER_PIXELS
);
415 ATTR(MAX_PBUFFER_WIDTH
);
416 ATTR(NATIVE_RENDERABLE
);
417 ATTR(NATIVE_VISUAL_ID
);
418 ATTR(NATIVE_VISUAL_TYPE
);
419 ATTR(PRESERVED_RESOURCES
);
421 ATTR(SAMPLE_BUFFERS
);
423 ATTR(TRANSPARENT_TYPE
);
424 ATTR(TRANSPARENT_RED_VALUE
);
425 ATTR(TRANSPARENT_GREEN_VALUE
);
426 ATTR(TRANSPARENT_BLUE_VALUE
);
427 ATTR(BIND_TO_TEXTURE_RGB
);
428 ATTR(BIND_TO_TEXTURE_RGBA
);
429 ATTR(MIN_SWAP_INTERVAL
);
430 ATTR(MAX_SWAP_INTERVAL
);
431 ATTR(LUMINANCE_SIZE
);
432 ATTR(ALPHA_MASK_SIZE
);
433 ATTR(COLOR_BUFFER_TYPE
);
434 ATTR(RENDERABLE_TYPE
);
441 GLLibraryEGL::DumpEGLConfigs()
444 fGetConfigs(mEGLDisplay
, nullptr, 0, &nc
);
445 EGLConfig
*ec
= new EGLConfig
[nc
];
446 fGetConfigs(mEGLDisplay
, ec
, nc
, &nc
);
448 for (int i
= 0; i
< nc
; ++i
) {
449 printf_stderr ("========= EGL Config %d ========\n", i
);
450 DumpEGLConfig(ec
[i
]);
458 GLLibraryEGL::BeforeGLCall(const char* glFunction
)
460 if (GLContext::DebugMode()) {
461 if (GLContext::DebugMode() & GLContext::DebugTrace
)
462 printf_stderr("[egl] > %s\n", glFunction
);
467 GLLibraryEGL::AfterGLCall(const char* glFunction
)
469 if (GLContext::DebugMode() & GLContext::DebugTrace
) {
470 printf_stderr("[egl] < %s\n", glFunction
);
476 } /* namespace mozilla */