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"
8 #include "gfxCrashReporterUtils.h"
11 #include "mozilla/Preferences.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/gfx/gfxVars.h"
14 #include "mozilla/gfx/Logging.h"
15 #include "mozilla/Telemetry.h"
16 #include "mozilla/Tokenizer.h"
17 #include "mozilla/ScopeExit.h"
18 #include "mozilla/StaticPrefs_gfx.h"
19 #include "mozilla/StaticPrefs_webgl.h"
20 #include "mozilla/Unused.h"
21 #include "mozilla/webrender/RenderThread.h"
22 #include "nsDirectoryServiceDefs.h"
23 #include "nsDirectoryServiceUtils.h"
24 #include "nsPrintfCString.h"
26 # include "mozilla/gfx/DeviceManagerDx.h"
27 # include "nsWindowsHelpers.h"
31 #include "OGLShaderProgram.h"
34 #include "GLContext.h"
35 #include "GLContextProvider.h"
36 #include "GLLibraryLoader.h"
37 #include "GLReadTexImageHelper.h"
38 #include "ScopedGLHelpers.h"
40 # include "mozilla/WidgetUtilsGtk.h"
42 # include "mozilla/widget/nsWaylandDisplay.h"
43 # endif // MOZ_WIDGET_GTK
47 #include <mutex> // for call_once
52 // should match the order of EGLExtensions, and be null-terminated.
53 static const char* sEGLLibraryExtensionNames
[] = {
54 "EGL_ANDROID_get_native_client_buffer", "EGL_ANGLE_device_creation",
55 "EGL_ANGLE_device_creation_d3d11", "EGL_ANGLE_platform_angle",
56 "EGL_ANGLE_platform_angle_d3d"};
58 // should match the order of EGLExtensions, and be null-terminated.
59 static const char* sEGLExtensionNames
[] = {
61 "EGL_KHR_image_pixmap",
62 "EGL_KHR_gl_texture_2D_image",
63 "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
64 "EGL_EXT_create_context_robustness",
68 "EGL_ANDROID_native_fence_sync",
69 "EGL_ANDROID_image_crop",
70 "EGL_ANGLE_d3d_share_handle_client_buffer",
71 "EGL_KHR_create_context",
73 "EGL_KHR_stream_consumer_gltexture",
74 "EGL_EXT_device_query",
75 "EGL_NV_stream_consumer_gltexture_yuv",
76 "EGL_ANGLE_stream_producer_d3d_texture",
77 "EGL_KHR_surfaceless_context",
78 "EGL_KHR_create_context_no_error",
79 "EGL_MOZ_create_context_provoking_vertex_dont_care",
80 "EGL_EXT_swap_buffers_with_damage",
81 "EGL_KHR_swap_buffers_with_damage",
83 "EGL_KHR_partial_update",
84 "EGL_NV_robustness_video_memory_purge"};
86 PRLibrary
* LoadApitraceLibrary() {
87 const char* path
= nullptr;
90 // We only need to explicitly dlopen egltrace
91 // on android as we can use LD_PRELOAD or other tricks
92 // on other platforms. We look for it in /data/local
93 // as that's writeable by all users.
94 path
= "/data/local/tmp/egltrace.so";
96 if (!path
) return nullptr;
98 // Initialization of gfx prefs here is only needed during the unit tests...
99 if (!StaticPrefs::gfx_apitrace_enabled_AtStartup()) {
103 static PRLibrary
* sApitraceLibrary
= nullptr;
104 if (sApitraceLibrary
) return sApitraceLibrary
;
106 nsAutoCString logFile
;
107 Preferences::GetCString("gfx.apitrace.logfile", logFile
);
108 if (logFile
.IsEmpty()) {
109 logFile
= "firefox.trace";
112 // The firefox process can't write to /data/local, but it can write
114 nsAutoCString logPath
;
115 logPath
.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile
.get());
117 #ifndef XP_WIN // Windows is missing setenv and forbids PR_LoadLibrary.
118 // apitrace uses the TRACE_FILE environment variable to determine where
119 // to log trace output to
120 printf_stderr("Logging GL tracing output to %s", logPath
.get());
121 setenv("TRACE_FILE", logPath
.get(), false);
123 printf_stderr("Attempting load of %s\n", path
);
124 sApitraceLibrary
= PR_LoadLibrary(path
);
127 return sApitraceLibrary
;
131 // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
132 static PRLibrary
* LoadLibraryForEGLOnWindows(const nsAString
& filename
) {
133 nsAutoString
path(gfx::gfxVars::GREDirectory());
134 path
.Append(PR_GetDirectorySeparator());
135 path
.Append(filename
);
138 lspec
.type
= PR_LibSpec_PathnameU
;
139 lspec
.value
.pathname_u
= path
.get();
140 return PR_LoadLibraryWithFlags(lspec
, PR_LD_LAZY
| PR_LD_LOCAL
);
145 static std::shared_ptr
<EglDisplay
> GetAndInitDisplay(GLLibraryEGL
& egl
,
147 const auto display
= egl
.fGetDisplay(displayType
);
148 if (!display
) return nullptr;
149 return EglDisplay::Create(egl
, display
, false);
152 static std::shared_ptr
<EglDisplay
> GetAndInitWARPDisplay(GLLibraryEGL
& egl
,
154 const EGLAttrib attrib_list
[] = {
155 LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE
,
156 LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE
,
158 LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE
,
159 LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
, LOCAL_EGL_NONE
};
160 const EGLDisplay display
= egl
.fGetPlatformDisplay(
161 LOCAL_EGL_PLATFORM_ANGLE_ANGLE
, displayType
, attrib_list
);
163 if (display
== EGL_NO_DISPLAY
) {
164 const EGLint err
= egl
.fGetError();
165 if (err
!= LOCAL_EGL_SUCCESS
) {
166 gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err
);
167 MOZ_CRASH("GFX: Unexpected GL error.");
172 return EglDisplay::Create(egl
, display
, true);
175 std::shared_ptr
<EglDisplay
> GLLibraryEGL::CreateDisplay(
176 ID3D11Device
* const d3d11Device
) {
177 EGLDeviceEXT eglDevice
=
178 fCreateDeviceANGLE(LOCAL_EGL_D3D11_DEVICE_ANGLE
, d3d11Device
, nullptr);
180 gfxCriticalNote
<< "Failed to get EGLDeviceEXT of D3D11Device";
183 const char* features
[] = {"allowES3OnFL10_0", nullptr};
184 // Create an EGLDisplay using the EGLDevice
185 const EGLAttrib attrib_list
[] = {LOCAL_EGL_FEATURE_OVERRIDES_ENABLED_ANGLE
,
186 reinterpret_cast<EGLAttrib
>(features
),
188 const auto display
= fGetPlatformDisplay(LOCAL_EGL_PLATFORM_DEVICE_EXT
,
189 eglDevice
, attrib_list
);
191 gfxCriticalNote
<< "Failed to get EGLDisplay of D3D11Device";
196 const EGLint err
= fGetError();
197 if (err
!= LOCAL_EGL_SUCCESS
) {
198 gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err
);
199 MOZ_CRASH("GFX: Unexpected GL error.");
204 const auto ret
= EglDisplay::Create(*this, display
, false);
207 const EGLint err
= fGetError();
208 if (err
!= LOCAL_EGL_SUCCESS
) {
210 << "Failed to initialize EGLDisplay for WebRender error: "
218 static bool IsAccelAngleSupported(nsACString
* const out_failureId
) {
219 if (wr::RenderThread::IsInRenderThread()) {
220 // We can only enter here with WebRender, so assert that this is a
221 // WebRender-enabled build.
224 if (!gfx::gfxVars::AllowWebglAccelAngle()) {
225 if (out_failureId
->IsEmpty()) {
226 *out_failureId
= "FEATURE_FAILURE_ACCL_ANGLE_NOT_OK"_ns
;
233 class AngleErrorReporting
{
235 AngleErrorReporting() : mFailureId(nullptr) {
236 // No static constructor
239 void SetFailureId(nsACString
* const aFailureId
) { mFailureId
= aFailureId
; }
241 void logError(const char* errorMessage
) {
246 nsCString
str(errorMessage
);
247 Tokenizer
tokenizer(str
);
249 // Parse "ANGLE Display::initialize error " << error.getID() << ": "
250 // << error.getMessage()
252 Tokenizer::Token intToken
;
253 if (tokenizer
.CheckWord("ANGLE") && tokenizer
.CheckWhite() &&
254 tokenizer
.CheckWord("Display") && tokenizer
.CheckChar(':') &&
255 tokenizer
.CheckChar(':') && tokenizer
.CheckWord("initialize") &&
256 tokenizer
.CheckWhite() && tokenizer
.CheckWord("error") &&
257 tokenizer
.CheckWhite() &&
258 tokenizer
.Check(Tokenizer::TOKEN_INTEGER
, intToken
)) {
259 *mFailureId
= "FAILURE_ID_ANGLE_ID_";
260 mFailureId
->AppendPrintf("%" PRIu64
, intToken
.AsInteger());
262 *mFailureId
= "FAILURE_ID_ANGLE_UNKNOWN";
267 nsACString
* mFailureId
;
270 AngleErrorReporting gAngleErrorReporter
;
272 static std::shared_ptr
<EglDisplay
> GetAndInitDisplayForAccelANGLE(
273 GLLibraryEGL
& egl
, nsACString
* const out_failureId
) {
274 MOZ_RELEASE_ASSERT(!wr::RenderThread::IsInRenderThread());
276 gfx::FeatureState
& d3d11ANGLE
=
277 gfx::gfxConfig::GetFeature(gfx::Feature::D3D11_HW_ANGLE
);
279 if (!StaticPrefs::webgl_angle_try_d3d11()) {
280 d3d11ANGLE
.UserDisable("User disabled D3D11 ANGLE by pref",
281 "FAILURE_ID_ANGLE_PREF"_ns
);
283 if (StaticPrefs::webgl_angle_force_d3d11()) {
284 d3d11ANGLE
.UserForceEnable(
285 "User force-enabled D3D11 ANGLE on disabled hardware");
287 gAngleErrorReporter
.SetFailureId(out_failureId
);
289 auto guardShutdown
= mozilla::MakeScopeExit([&] {
290 gAngleErrorReporter
.SetFailureId(nullptr);
291 // NOTE: Ideally we should be calling ANGLEPlatformShutdown after the
292 // ANGLE display is destroyed. However gAngleErrorReporter
293 // will live longer than the ANGLE display so we're fine.
296 if (gfx::gfxConfig::IsForcedOnByUser(gfx::Feature::D3D11_HW_ANGLE
)) {
297 return GetAndInitDisplay(egl
, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE
);
300 std::shared_ptr
<EglDisplay
> ret
;
301 if (d3d11ANGLE
.IsEnabled()) {
302 ret
= GetAndInitDisplay(egl
, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE
);
306 ret
= GetAndInitDisplay(egl
, EGL_DEFAULT_DISPLAY
);
309 if (!ret
&& out_failureId
->IsEmpty()) {
310 *out_failureId
= "FEATURE_FAILURE_ACCL_ANGLE_NO_DISP"_ns
;
319 # define GLES2_LIB "libGLESv2.so"
320 # define GLES2_LIB2 "libGLESv2.so.2"
321 # define GL_LIB "libGL.so"
322 # define GL_LIB2 "libGL.so.1"
323 #elif defined(XP_WIN)
324 # define GLES2_LIB "libGLESv2.dll"
326 # error "Platform not recognized"
329 Maybe
<SymbolLoader
> GLLibraryEGL::GetSymbolLoader() const {
330 auto ret
= SymbolLoader(mSymbols
.fGetProcAddress
);
331 ret
.mLib
= mGLLibrary
;
338 RefPtr
<GLLibraryEGL
> GLLibraryEGL::Create(nsACString
* const out_failureId
) {
339 RefPtr
<GLLibraryEGL
> ret
= new GLLibraryEGL
;
340 if (!ret
->Init(out_failureId
)) {
346 bool GLLibraryEGL::Init(nsACString
* const out_failureId
) {
347 MOZ_RELEASE_ASSERT(!mSymbols
.fTerminate
);
349 mozilla::ScopedGfxFeatureReporter
reporter("EGL");
353 // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul
354 // and we should look for them there. We have to load the libs in this
355 // order, because libEGL.dll depends on libGLESv2.dll which depends on the
356 // DXSDK libraries. This matters especially for WebRT apps which are in a
357 // different directory. See bug 760323 and bug 749459
359 // Also note that we intentionally leak the libs we load.
362 // Windows 8.1+ has d3dcompiler_47.dll in the system directory.
363 // Try it first. Note that _46 will never be in the system
364 // directory. So there is no point trying _46 in the system
367 if (LoadLibrarySystem32(L
"d3dcompiler_47.dll")) break;
369 # ifdef MOZ_D3DCOMPILER_VISTA_DLL
370 if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING_FROM_CSTRING(
371 MOZ_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL
))))
375 MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
378 mGLLibrary
= LoadLibraryForEGLOnWindows(u
"libGLESv2.dll"_ns
);
380 mEGLLibrary
= LoadLibraryForEGLOnWindows(u
"libEGL.dll"_ns
);
385 // On non-Windows (Android) we use system copies of libEGL. We look for
386 // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
388 # if defined(ANDROID)
389 if (!mEGLLibrary
) mEGLLibrary
= LoadApitraceLibrary();
393 mEGLLibrary
= PR_LoadLibrary("libEGL.so");
395 # if defined(XP_UNIX)
397 mEGLLibrary
= PR_LoadLibrary("libEGL.so.1");
403 mGLLibrary
= PR_LoadLibrary(APITRACE_LIB
);
409 mGLLibrary
= PR_LoadLibrary(GL_LIB
);
415 mGLLibrary
= PR_LoadLibrary(GL_LIB2
);
420 mGLLibrary
= PR_LoadLibrary(GLES2_LIB
);
425 mGLLibrary
= PR_LoadLibrary(GLES2_LIB2
);
431 if (!mEGLLibrary
|| !mGLLibrary
) {
432 NS_WARNING("Couldn't load EGL LIB.");
433 *out_failureId
= "FEATURE_FAILURE_EGL_LOAD_3"_ns
;
439 (PRFuncPtr*)&mSymbols.f##X, { \
443 #define END_OF_SYMBOLS \
448 SymLoadStruct earlySymbols
[] = {SYMBOL(GetDisplay
),
450 SYMBOL(GetCurrentSurface
),
451 SYMBOL(GetCurrentContext
),
453 SYMBOL(DestroyContext
),
454 SYMBOL(CreateContext
),
455 SYMBOL(DestroySurface
),
456 SYMBOL(CreateWindowSurface
),
457 SYMBOL(CreatePbufferSurface
),
458 SYMBOL(CreatePbufferFromClientBuffer
),
459 SYMBOL(CreatePixmapSurface
),
462 SYMBOL(ChooseConfig
),
465 SYMBOL(GetConfigAttrib
),
467 SYMBOL(GetProcAddress
),
471 SYMBOL(QueryContext
),
472 SYMBOL(BindTexImage
),
473 SYMBOL(ReleaseTexImage
),
474 SYMBOL(SwapInterval
),
475 SYMBOL(QuerySurface
),
479 const SymbolLoader
libLoader(*mEGLLibrary
);
480 if (!libLoader
.LoadSymbols(earlySymbols
)) {
482 "Couldn't find required entry points in EGL library (early init)");
483 *out_failureId
= "FEATURE_FAILURE_EGL_SYM"_ns
;
489 const char internalFuncName
[] =
490 "_Z35eglQueryStringImplementationANDROIDPvi";
491 const auto& internalFunc
=
492 PR_FindFunctionSymbol(mEGLLibrary
, internalFuncName
);
494 *(PRFuncPtr
*)&mSymbols
.fQueryString
= internalFunc
;
502 const SymbolLoader
pfnLoader(mSymbols
.fGetProcAddress
);
504 const auto fnLoadSymbols
= [&](const SymLoadStruct
* symbols
) {
505 const bool shouldWarn
= gfxEnv::GlSpew();
506 if (pfnLoader
.LoadSymbols(symbols
, shouldWarn
)) return true;
508 ClearSymbols(symbols
);
512 // Check the ANGLE support the system has
513 mIsANGLE
= IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle
);
515 // Client exts are ready. (But not display exts!)
518 MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d
));
519 const SymLoadStruct angleSymbols
[] = {SYMBOL(GetPlatformDisplay
),
521 if (!fnLoadSymbols(angleSymbols
)) {
522 gfxCriticalError() << "Failed to load ANGLE symbols!";
525 MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d
));
526 const SymLoadStruct createDeviceSymbols
[] = {
527 SYMBOL(CreateDeviceANGLE
), SYMBOL(ReleaseDeviceANGLE
), END_OF_SYMBOLS
};
528 if (!fnLoadSymbols(createDeviceSymbols
)) {
530 "EGL supports ANGLE_device_creation without exposing its functions!");
531 MarkExtensionUnsupported(EGLLibExtension::ANGLE_device_creation
);
535 // ANDROID_get_native_client_buffer isn't necessarily enumerated in lib exts,
538 const SymLoadStruct symbols
[] = {SYMBOL(GetNativeClientBufferANDROID
),
540 if (fnLoadSymbols(symbols
)) {
541 mAvailableExtensions
[UnderlyingValue(
542 EGLLibExtension::ANDROID_get_native_client_buffer
)] = true;
547 // Load possible display ext symbols.
550 const SymLoadStruct symbols
[] = {SYMBOL(QuerySurfacePointerANGLE
),
552 (void)fnLoadSymbols(symbols
);
555 const SymLoadStruct symbols
[] = {
556 SYMBOL(CreateSyncKHR
), SYMBOL(DestroySyncKHR
),
557 SYMBOL(ClientWaitSyncKHR
), SYMBOL(GetSyncAttribKHR
), END_OF_SYMBOLS
};
558 (void)fnLoadSymbols(symbols
);
561 const SymLoadStruct symbols
[] = {SYMBOL(CreateImageKHR
),
562 SYMBOL(DestroyImageKHR
), END_OF_SYMBOLS
};
563 (void)fnLoadSymbols(symbols
);
566 const SymLoadStruct symbols
[] = {SYMBOL(WaitSyncKHR
), END_OF_SYMBOLS
};
567 (void)fnLoadSymbols(symbols
);
570 const SymLoadStruct symbols
[] = {SYMBOL(DupNativeFenceFDANDROID
),
572 (void)fnLoadSymbols(symbols
);
575 const SymLoadStruct symbols
[] = {SYMBOL(CreateStreamKHR
),
576 SYMBOL(DestroyStreamKHR
),
577 SYMBOL(QueryStreamKHR
), END_OF_SYMBOLS
};
578 (void)fnLoadSymbols(symbols
);
581 const SymLoadStruct symbols
[] = {SYMBOL(StreamConsumerGLTextureExternalKHR
),
582 SYMBOL(StreamConsumerAcquireKHR
),
583 SYMBOL(StreamConsumerReleaseKHR
),
585 (void)fnLoadSymbols(symbols
);
588 const SymLoadStruct symbols
[] = {SYMBOL(QueryDisplayAttribEXT
),
589 SYMBOL(QueryDeviceAttribEXT
),
591 (void)fnLoadSymbols(symbols
);
594 const SymLoadStruct symbols
[] = {
595 SYMBOL(StreamConsumerGLTextureExternalAttribsNV
), END_OF_SYMBOLS
};
596 (void)fnLoadSymbols(symbols
);
599 const SymLoadStruct symbols
[] = {
600 SYMBOL(CreateStreamProducerD3DTextureANGLE
),
601 SYMBOL(StreamPostD3DTextureANGLE
), END_OF_SYMBOLS
};
602 (void)fnLoadSymbols(symbols
);
605 const SymLoadStruct symbols
[] = {
606 {(PRFuncPtr
*)&mSymbols
.fSwapBuffersWithDamage
,
607 {{"eglSwapBuffersWithDamageEXT"}}},
609 (void)fnLoadSymbols(symbols
);
612 const SymLoadStruct symbols
[] = {
613 {(PRFuncPtr
*)&mSymbols
.fSwapBuffersWithDamage
,
614 {{"eglSwapBuffersWithDamageKHR"}}},
616 (void)fnLoadSymbols(symbols
);
619 const SymLoadStruct symbols
[] = {
620 {(PRFuncPtr
*)&mSymbols
.fSetDamageRegion
, {{"eglSetDamageRegionKHR"}}},
622 (void)fnLoadSymbols(symbols
);
631 static void MarkExtensions(const char* rawExtString
, bool shouldDumpExts
,
632 const char* extType
, const char* const (&names
)[N
],
633 std::bitset
<N
>* const out
) {
634 MOZ_ASSERT(rawExtString
);
636 const nsDependentCString
extString(rawExtString
);
638 std::vector
<nsCString
> extList
;
639 SplitByChar(extString
, ' ', &extList
);
641 if (shouldDumpExts
) {
642 printf_stderr("%u EGL %s extensions: (*: recognized)\n",
643 (uint32_t)extList
.size(), extType
);
646 MarkBitfieldByStrings(extList
, shouldDumpExts
, names
, out
);
652 std::shared_ptr
<EglDisplay
> EglDisplay::Create(GLLibraryEGL
& lib
,
653 const EGLDisplay display
,
655 // Retrieve the EglDisplay if it already exists
657 const auto itr
= lib
.mActiveDisplays
.find(display
);
658 if (itr
!= lib
.mActiveDisplays
.end()) {
659 const auto ret
= itr
->second
.lock();
666 if (!lib
.fInitialize(display
, nullptr, nullptr)) {
670 static std::once_flag sMesaLeakFlag
;
671 std::call_once(sMesaLeakFlag
, MesaMemoryLeakWorkaround
);
674 std::make_shared
<EglDisplay
>(PrivateUseOnly
{}, lib
, display
, isWarp
);
675 lib
.mActiveDisplays
.insert({display
, ret
});
679 EglDisplay::EglDisplay(const PrivateUseOnly
&, GLLibraryEGL
& lib
,
680 const EGLDisplay disp
, const bool isWarp
)
681 : mLib(&lib
), mDisplay(disp
), mIsWARP(isWarp
) {
682 const bool shouldDumpExts
= GLContext::ShouldDumpExts();
685 (const char*)mLib
->fQueryString(mDisplay
, LOCAL_EGL_EXTENSIONS
);
687 NS_WARNING("Failed to query EGL display extensions!.");
690 MarkExtensions(rawExtString
, shouldDumpExts
, "display", sEGLExtensionNames
,
691 &mAvailableExtensions
);
695 if (!HasKHRImageBase()) {
696 MarkExtensionUnsupported(EGLExtension::KHR_image_pixmap
);
699 if (IsExtensionSupported(EGLExtension::KHR_surfaceless_context
)) {
701 (const char*)mLib
->fQueryString(mDisplay
, LOCAL_EGL_VENDOR
);
703 // Bug 1464610: Mali T720 (Amazon Fire 8 HD) claims to support this
704 // extension, but if you actually eglMakeCurrent() with EGL_NO_SURFACE, it
705 // fails to render anything when a real surface is provided later on. We
706 // only have the EGL vendor available here, so just avoid using this
707 // extension on all Mali devices.
708 if (strcmp(vendor
, "ARM") == 0) {
709 MarkExtensionUnsupported(EGLExtension::KHR_surfaceless_context
);
713 // ANDROID_native_fence_sync isn't necessarily enumerated in display ext,
715 if (mLib
->mSymbols
.fDupNativeFenceFDANDROID
) {
716 mAvailableExtensions
[UnderlyingValue(
717 EGLExtension::ANDROID_native_fence_sync
)] = true;
721 EglDisplay::~EglDisplay() {
723 mLib
->mActiveDisplays
.erase(mDisplay
);
728 std::shared_ptr
<EglDisplay
> GLLibraryEGL::DefaultDisplay(
729 nsACString
* const out_failureId
) {
730 auto ret
= mDefaultDisplay
.lock();
733 ret
= CreateDisplay(false, out_failureId
);
734 mDefaultDisplay
= ret
;
738 std::shared_ptr
<EglDisplay
> GLLibraryEGL::CreateDisplay(
739 const bool forceAccel
, nsACString
* const out_failureId
) {
740 std::shared_ptr
<EglDisplay
> ret
;
742 if (IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d
)) {
743 nsCString accelAngleFailureId
;
744 bool accelAngleSupport
= IsAccelAngleSupported(&accelAngleFailureId
);
745 bool shouldTryAccel
= forceAccel
|| accelAngleSupport
;
746 bool shouldTryWARP
= !forceAccel
; // Only if ANGLE not supported or fails
748 // If WARP preferred, will override ANGLE support
749 if (StaticPrefs::webgl_angle_force_warp()) {
750 shouldTryWARP
= true;
751 shouldTryAccel
= false;
752 if (accelAngleFailureId
.IsEmpty()) {
753 accelAngleFailureId
= "FEATURE_FAILURE_FORCE_WARP"_ns
;
757 // Hardware accelerated ANGLE path (supported or force accel)
758 if (shouldTryAccel
) {
759 ret
= GetAndInitDisplayForAccelANGLE(*this, out_failureId
);
762 // Report the acceleration status to telemetry
764 if (accelAngleFailureId
.IsEmpty()) {
765 Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID
,
766 "FEATURE_FAILURE_ACCL_ANGLE_UNKNOWN"_ns
);
768 Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID
,
769 accelAngleFailureId
);
772 Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID
,
776 // Fallback to a WARP display if ANGLE fails, or if WARP is forced
777 if (!ret
&& shouldTryWARP
) {
778 ret
= GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY
);
780 if (out_failureId
->IsEmpty()) {
781 *out_failureId
= "FEATURE_FAILURE_WARP_FALLBACK"_ns
;
783 NS_ERROR("Fallback WARP context failed to initialize.");
788 void* nativeDisplay
= EGL_DEFAULT_DISPLAY
;
790 // Some drivers doesn't support EGL_DEFAULT_DISPLAY
791 GdkDisplay
* gdkDisplay
= gdk_display_get_default();
792 if (widget::GdkIsWaylandDisplay(gdkDisplay
)) {
793 nativeDisplay
= widget::WaylandDisplayGetWLDisplay(gdkDisplay
);
794 if (!nativeDisplay
) {
795 NS_WARNING("Failed to get wl_display.");
800 ret
= GetAndInitDisplay(*this, nativeDisplay
);
804 if (out_failureId
->IsEmpty()) {
805 *out_failureId
= "FEATURE_FAILURE_NO_DISPLAY"_ns
;
807 NS_WARNING("Failed to initialize a display.");
814 void GLLibraryEGL::InitLibExtensions() {
815 const bool shouldDumpExts
= GLContext::ShouldDumpExts();
817 const char* rawExtString
= nullptr;
820 // Bug 1209612: Crashes on a number of android drivers.
821 // Ideally we would only blocklist this there, but for now we don't need the
822 // client extension list on ANDROID (we mostly need it on ANGLE), and we'd
824 rawExtString
= (const char*)fQueryString(nullptr, LOCAL_EGL_EXTENSIONS
);
828 if (shouldDumpExts
) {
829 printf_stderr("No EGL lib extensions.\n");
834 MarkExtensions(rawExtString
, shouldDumpExts
, "lib", sEGLLibraryExtensionNames
,
835 &mAvailableExtensions
);
838 void EglDisplay::DumpEGLConfig(EGLConfig cfg
) const {
842 mLib->fGetConfigAttrib(mDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
843 const auto err = mLib->fGetError(); \
844 if (err != 0x3000) { \
845 printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
847 printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
851 printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg
, cfg
);
863 ATTR(MAX_PBUFFER_HEIGHT
);
864 ATTR(MAX_PBUFFER_PIXELS
);
865 ATTR(MAX_PBUFFER_WIDTH
);
866 ATTR(NATIVE_RENDERABLE
);
867 ATTR(NATIVE_VISUAL_ID
);
868 ATTR(NATIVE_VISUAL_TYPE
);
869 ATTR(PRESERVED_RESOURCES
);
871 ATTR(SAMPLE_BUFFERS
);
873 ATTR(TRANSPARENT_TYPE
);
874 ATTR(TRANSPARENT_RED_VALUE
);
875 ATTR(TRANSPARENT_GREEN_VALUE
);
876 ATTR(TRANSPARENT_BLUE_VALUE
);
877 ATTR(BIND_TO_TEXTURE_RGB
);
878 ATTR(BIND_TO_TEXTURE_RGBA
);
879 ATTR(MIN_SWAP_INTERVAL
);
880 ATTR(MAX_SWAP_INTERVAL
);
881 ATTR(LUMINANCE_SIZE
);
882 ATTR(ALPHA_MASK_SIZE
);
883 ATTR(COLOR_BUFFER_TYPE
);
884 ATTR(RENDERABLE_TYPE
);
890 void EglDisplay::DumpEGLConfigs() const {
892 mLib
->fGetConfigs(mDisplay
, nullptr, 0, &nc
);
893 std::vector
<EGLConfig
> ec(nc
);
894 mLib
->fGetConfigs(mDisplay
, ec
.data(), ec
.size(), &nc
);
896 for (int i
= 0; i
< nc
; ++i
) {
897 printf_stderr("========= EGL Config %d ========\n", i
);
898 DumpEGLConfig(ec
[i
]);
902 static bool ShouldTrace() {
903 static bool ret
= gfxEnv::GlDebugVerbose();
907 void BeforeEGLCall(const char* glFunction
) {
909 printf_stderr("[egl] > %s\n", glFunction
);
913 void AfterEGLCall(const char* glFunction
) {
915 printf_stderr("[egl] < %s\n", glFunction
);
920 } /* namespace mozilla */