Bumping manifests a=b2g-bump
[gecko.git] / gfx / gl / GLLibraryEGL.cpp
bloba5ee2056f977d9a881cb1d3aa716bd2e151493c4
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 nullptr
42 #if defined(ANDROID)
44 static PRLibrary* LoadApitraceLibrary()
46 if (!gfxPrefs::UseApitrace()) {
47 return nullptr;
50 static PRLibrary* sApitraceLibrary = nullptr;
52 if (sApitraceLibrary)
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
62 // to $GRE_HOME/
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;
78 #endif // ANDROID
80 #ifdef XP_WIN
81 // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
82 static PRLibrary*
83 LoadLibraryForEGLOnWindows(const nsAString& filename)
85 nsCOMPtr<nsIFile> file;
86 nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
87 if (NS_FAILED(rv))
88 return nullptr;
90 file->Append(filename);
91 PRLibrary* lib = nullptr;
92 rv = file->Load(&lib);
93 if (NS_FAILED(rv)) {
94 nsPrintfCString msg("Failed to load %s - Expect EGL initialization to fail",
95 NS_LossyConvertUTF16toASCII(filename).get());
96 NS_WARNING(msg.get());
98 return lib;
100 #endif // XP_WIN
102 bool
103 GLLibraryEGL::EnsureInitialized()
105 if (mInitialized) {
106 return true;
109 mozilla::ScopedGfxFeatureReporter reporter("EGL");
111 #ifdef MOZ_B2G
112 if (!sCurrentContext.init())
113 MOZ_CRASH("Tls init failed");
114 #endif
116 #ifdef XP_WIN
117 if (!mEGLLibrary) {
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.
126 do {
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"))
133 break;
135 #ifdef MOZ_D3DCOMPILER_VISTA_DLL
136 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL))))
137 break;
138 #endif
140 #ifdef MOZ_D3DCOMPILER_XP_DLL
141 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_XP_DLL))))
142 break;
143 #endif
145 MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
146 } while (false);
148 LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
150 mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
152 if (!mEGLLibrary)
153 return false;
156 #else // !Windows
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.
161 #if defined(ANDROID)
162 if (!mEGLLibrary)
163 mEGLLibrary = LoadApitraceLibrary();
164 #endif
166 if (!mEGLLibrary) {
167 printf_stderr("Attempting load of libEGL.so\n");
168 mEGLLibrary = PR_LoadLibrary("libEGL.so");
170 #if defined(XP_UNIX)
171 if (!mEGLLibrary) {
172 mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
174 #endif
176 if (!mEGLLibrary) {
177 NS_WARNING("Couldn't load EGL LIB.");
178 return false;
181 #endif // !Windows
183 #define SYMBOL(name) \
184 { (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }
186 GLLibraryLoader::SymLoadStruct earlySymbols[] = {
187 SYMBOL(GetDisplay),
188 SYMBOL(GetCurrentSurface),
189 SYMBOL(GetCurrentContext),
190 SYMBOL(MakeCurrent),
191 SYMBOL(DestroyContext),
192 SYMBOL(CreateContext),
193 SYMBOL(DestroySurface),
194 SYMBOL(CreateWindowSurface),
195 SYMBOL(CreatePbufferSurface),
196 SYMBOL(CreatePixmapSurface),
197 SYMBOL(BindAPI),
198 SYMBOL(Initialize),
199 SYMBOL(ChooseConfig),
200 SYMBOL(GetError),
201 SYMBOL(GetConfigs),
202 SYMBOL(GetConfigAttrib),
203 SYMBOL(WaitNative),
204 SYMBOL(GetProcAddress),
205 SYMBOL(SwapBuffers),
206 SYMBOL(CopyBuffers),
207 SYMBOL(QueryString),
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)");
217 return false;
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");
233 #endif
235 mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
236 if (!fInitialize(mEGLDisplay, nullptr, nullptr))
237 return false;
239 const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
240 if (vendor && (strstr(vendor, "TransGaming") != 0 || strstr(vendor, "Google Inc.") != 0)) {
241 mIsANGLE = true;
244 InitExtensions();
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,
257 &lockSymbols[0],
258 lookupFunction);
259 if (!success) {
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,
276 &d3dSymbols[0],
277 lookupFunction);
278 if (!success) {
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,
297 &syncSymbols[0],
298 lookupFunction);
299 if (!success) {
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,
319 &imageSymbols[0],
320 lookupFunction);
321 if (!success) {
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;
331 } else {
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],
343 lookupFunction);
344 if (!success) {
345 NS_ERROR("EGL supports ANDROID_native_fence_sync without exposing its functions!");
347 MarkExtensionUnsupported(ANDROID_native_fence_sync);
349 mSymbols.fDupNativeFenceFDANDROID = nullptr;
353 mInitialized = true;
354 reporter.SetSuccessful();
355 return true;
358 void
359 GLLibraryEGL::InitExtensions()
361 const char *extensions = (const char*)fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
363 if (!extensions) {
364 NS_WARNING("Failed to load EGL extension list!");
365 return;
368 bool debugMode = false;
369 #ifdef DEBUG
370 if (PR_GetEnv("MOZ_GL_DEBUG"))
371 debugMode = true;
373 static bool firstRun = true;
374 #else
375 // Non-DEBUG, so never spew.
376 const bool firstRun = false;
377 #endif
379 GLContext::InitializeExtensionsBitSet(mAvailableExtensions, extensions, sEGLExtensionNames, firstRun && debugMode);
381 #ifdef DEBUG
382 firstRun = false;
383 #endif
386 void
387 GLLibraryEGL::DumpEGLConfig(EGLConfig cfg)
389 int attrval;
390 int err;
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); \
396 } else { \
397 printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
399 } while(0)
401 printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
403 ATTR(BUFFER_SIZE);
404 ATTR(ALPHA_SIZE);
405 ATTR(BLUE_SIZE);
406 ATTR(GREEN_SIZE);
407 ATTR(RED_SIZE);
408 ATTR(DEPTH_SIZE);
409 ATTR(STENCIL_SIZE);
410 ATTR(CONFIG_CAVEAT);
411 ATTR(CONFIG_ID);
412 ATTR(LEVEL);
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);
420 ATTR(SAMPLES);
421 ATTR(SAMPLE_BUFFERS);
422 ATTR(SURFACE_TYPE);
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);
435 ATTR(CONFORMANT);
437 #undef ATTR
440 void
441 GLLibraryEGL::DumpEGLConfigs()
443 int nc = 0;
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]);
453 delete [] ec;
456 #ifdef DEBUG
457 /*static*/ void
458 GLLibraryEGL::BeforeGLCall(const char* glFunction)
460 if (GLContext::DebugMode()) {
461 if (GLContext::DebugMode() & GLContext::DebugTrace)
462 printf_stderr("[egl] > %s\n", glFunction);
466 /*static*/ void
467 GLLibraryEGL::AfterGLCall(const char* glFunction)
469 if (GLContext::DebugMode() & GLContext::DebugTrace) {
470 printf_stderr("[egl] < %s\n", glFunction);
473 #endif
475 } /* namespace gl */
476 } /* namespace mozilla */