Bumping manifests a=b2g-bump
[gecko.git] / gfx / gl / GLLibraryEGL.cpp
blobb937372e4a9659138ab97522bce35655b3e5a501
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"
13 #ifdef XP_WIN
14 #include "nsWindowsHelpers.h"
15 #endif
16 #include "prenv.h"
17 #include "GLContext.h"
18 #include "gfxPrefs.h"
20 namespace mozilla {
21 namespace gl {
23 GLLibraryEGL sEGLLibrary;
24 #ifdef MOZ_B2G
25 ThreadLocal<EGLContext> GLLibraryEGL::sCurrentContext;
26 #endif
28 // should match the order of EGLExtensions, and be null-terminated.
29 static const char *sEGLExtensionNames[] = {
30 "EGL_KHR_image_base",
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",
36 "EGL_KHR_image",
37 "EGL_KHR_fence_sync",
38 "EGL_ANDROID_native_fence_sync",
39 "EGL_ANDROID_image_crop",
40 nullptr
43 #if defined(ANDROID)
45 static PRLibrary* LoadApitraceLibrary()
47 if (!gfxPrefs::UseApitrace()) {
48 return nullptr;
51 static PRLibrary* sApitraceLibrary = nullptr;
53 if (sApitraceLibrary)
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
63 // to $GRE_HOME/
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;
79 #endif // ANDROID
81 #ifdef XP_WIN
82 // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
83 static PRLibrary*
84 LoadLibraryForEGLOnWindows(const nsAString& filename)
86 nsCOMPtr<nsIFile> file;
87 nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
88 if (NS_FAILED(rv))
89 return nullptr;
91 file->Append(filename);
92 PRLibrary* lib = nullptr;
93 rv = file->Load(&lib);
94 if (NS_FAILED(rv)) {
95 nsPrintfCString msg("Failed to load %s - Expect EGL initialization to fail",
96 NS_LossyConvertUTF16toASCII(filename).get());
97 NS_WARNING(msg.get());
99 return lib;
101 #endif // XP_WIN
103 static EGLDisplay
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;
113 return display;
116 bool
117 GLLibraryEGL::EnsureInitialized()
119 if (mInitialized) {
120 return true;
123 mozilla::ScopedGfxFeatureReporter reporter("EGL");
125 #ifdef MOZ_B2G
126 if (!sCurrentContext.init())
127 MOZ_CRASH("Tls init failed");
128 #endif
130 #ifdef XP_WIN
131 if (!mEGLLibrary) {
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.
140 do {
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"))
147 break;
149 #ifdef MOZ_D3DCOMPILER_VISTA_DLL
150 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL))))
151 break;
152 #endif
154 #ifdef MOZ_D3DCOMPILER_XP_DLL
155 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_XP_DLL))))
156 break;
157 #endif
159 MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
160 } while (false);
162 LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
164 mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
166 if (!mEGLLibrary)
167 return false;
170 #else // !Windows
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.
175 #if defined(ANDROID)
176 if (!mEGLLibrary)
177 mEGLLibrary = LoadApitraceLibrary();
178 #endif
180 if (!mEGLLibrary) {
181 printf_stderr("Attempting load of libEGL.so\n");
182 mEGLLibrary = PR_LoadLibrary("libEGL.so");
184 #if defined(XP_UNIX)
185 if (!mEGLLibrary) {
186 mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
188 #endif
190 if (!mEGLLibrary) {
191 NS_WARNING("Couldn't load EGL LIB.");
192 return false;
195 #endif // !Windows
197 #define SYMBOL(name) \
198 { (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }
200 GLLibraryLoader::SymLoadStruct earlySymbols[] = {
201 SYMBOL(GetDisplay),
202 SYMBOL(Terminate),
203 SYMBOL(GetCurrentSurface),
204 SYMBOL(GetCurrentContext),
205 SYMBOL(MakeCurrent),
206 SYMBOL(DestroyContext),
207 SYMBOL(CreateContext),
208 SYMBOL(DestroySurface),
209 SYMBOL(CreateWindowSurface),
210 SYMBOL(CreatePbufferSurface),
211 SYMBOL(CreatePixmapSurface),
212 SYMBOL(BindAPI),
213 SYMBOL(Initialize),
214 SYMBOL(ChooseConfig),
215 SYMBOL(GetError),
216 SYMBOL(GetConfigs),
217 SYMBOL(GetConfigAttrib),
218 SYMBOL(WaitNative),
219 SYMBOL(GetProcAddress),
220 SYMBOL(SwapBuffers),
221 SYMBOL(CopyBuffers),
222 SYMBOL(QueryString),
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)");
232 return false;
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");
250 #endif
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))
258 mIsANGLE = true;
261 if (mIsANGLE) {
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);
289 InitExtensions();
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,
302 &lockSymbols[0],
303 lookupFunction);
304 if (!success) {
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,
321 &d3dSymbols[0],
322 lookupFunction);
323 if (!success) {
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,
340 &d3dSymbols[0],
341 lookupFunction);
342 if (!success) {
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,
361 &syncSymbols[0],
362 lookupFunction);
363 if (!success) {
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,
383 &imageSymbols[0],
384 lookupFunction);
385 if (!success) {
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;
395 } else {
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],
407 lookupFunction);
408 if (!success) {
409 NS_ERROR("EGL supports ANDROID_native_fence_sync without exposing its functions!");
411 MarkExtensionUnsupported(ANDROID_native_fence_sync);
413 mSymbols.fDupNativeFenceFDANDROID = nullptr;
417 mInitialized = true;
418 reporter.SetSuccessful();
419 return true;
422 void
423 GLLibraryEGL::InitExtensions()
425 const char *extensions = (const char*)fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
427 if (!extensions) {
428 NS_WARNING("Failed to load EGL extension list!");
429 return;
432 GLContext::InitializeExtensionsBitSet(mAvailableExtensions, extensions,
433 sEGLExtensionNames);
436 void
437 GLLibraryEGL::DumpEGLConfig(EGLConfig cfg)
439 int attrval;
440 int err;
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); \
446 } else { \
447 printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
449 } while(0)
451 printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
453 ATTR(BUFFER_SIZE);
454 ATTR(ALPHA_SIZE);
455 ATTR(BLUE_SIZE);
456 ATTR(GREEN_SIZE);
457 ATTR(RED_SIZE);
458 ATTR(DEPTH_SIZE);
459 ATTR(STENCIL_SIZE);
460 ATTR(CONFIG_CAVEAT);
461 ATTR(CONFIG_ID);
462 ATTR(LEVEL);
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);
470 ATTR(SAMPLES);
471 ATTR(SAMPLE_BUFFERS);
472 ATTR(SURFACE_TYPE);
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);
485 ATTR(CONFORMANT);
487 #undef ATTR
490 void
491 GLLibraryEGL::DumpEGLConfigs()
493 int nc = 0;
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]);
503 delete [] ec;
506 #ifdef DEBUG
507 /*static*/ void
508 GLLibraryEGL::BeforeGLCall(const char* glFunction)
510 if (GLContext::DebugMode()) {
511 if (GLContext::DebugMode() & GLContext::DebugTrace)
512 printf_stderr("[egl] > %s\n", glFunction);
516 /*static*/ void
517 GLLibraryEGL::AfterGLCall(const char* glFunction)
519 if (GLContext::DebugMode() & GLContext::DebugTrace) {
520 printf_stderr("[egl] < %s\n", glFunction);
523 #endif
525 } /* namespace gl */
526 } /* namespace mozilla */