tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit ac30d4d7974faeacc0816c65d88d75e016979d91
parent f28145d2a08b325bf69ab8d27c7726f0984f9d18
Author: stransky <stransky@redhat.com>
Date:   Tue,  6 Jan 2026 19:12:02 +0000

Bug 2001628 [Linux] Make mWindowSurface persistent r=emilio

Right now we create/delete WindowSurface on nsWindow map/unmap event. In this patch we make it persistent
and keep it until nsWindow::Destroy().

Changes:

- Initialize SurfaceProvider at nsWindow::Create() and release at nsWindow::Destroy() so remove ConfigureCompositor/ResumeCompositorImpl() as it's not needed.
- Remove SurfaceProvider::mWindowSurfaceValid as it's always valid (if it's present).
- Start nsWindow VSync source at nsWindow::Create() and stop at nsWindow::Destroy() as we can always paint (even to offscreen / hidden nsWindow).
- Remove nsIWidget::IsMapped() and enable WebRender transaction throttle as we do on other arches - we can always paint now.
- Remove offscreen fallback from GLContextEGL::CreateEGLSurfaceForCompositorWidget() as we always have valid EGLSurface to draw into.
- Set EGLSurface at RenderCompositorEGL::RenderCompositorEGL() instead of fetch at Resume().
- Remove GtkCompositorWidget::SetRenderingSurface() as it's not needed.
- Remove WindowSurfaceProvider mWindowSurface mutex and thread safety hacks.

Differential Revision: https://phabricator.services.mozilla.com/D276964

Diffstat:
Mgfx/gl/GLContextProviderEGL.cpp | 18------------------
Mgfx/layers/wr/WebRenderLayerManager.cpp | 10++++------
Mgfx/webrender_bindings/RenderCompositorEGL.cpp | 54+++++++++++++++++++++++++++++++-----------------------
Mgfx/webrender_bindings/RenderCompositorOGLSWGL.cpp | 8--------
Mgfx/webrender_bindings/RenderCompositorSWGL.cpp | 2--
Mwidget/gtk/CompositorWidgetChild.cpp | 4----
Mwidget/gtk/CompositorWidgetChild.h | 1-
Mwidget/gtk/CompositorWidgetParent.cpp | 6------
Mwidget/gtk/CompositorWidgetParent.h | 2--
Mwidget/gtk/GtkCompositorWidget.cpp | 17-----------------
Mwidget/gtk/GtkCompositorWidget.h | 4----
Mwidget/gtk/PCompositorWidget.ipdl | 1-
Mwidget/gtk/WindowSurfaceProvider.cpp | 53+----------------------------------------------------
Mwidget/gtk/WindowSurfaceProvider.h | 17+----------------
Mwidget/gtk/nsWindow.cpp | 138+++++++++++++++++--------------------------------------------------------------
Mwidget/gtk/nsWindow.h | 9+--------
Mwidget/nsIWidget.h | 8--------
17 files changed, 68 insertions(+), 284 deletions(-)

diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp @@ -339,26 +339,8 @@ EGLSurface GLContextEGL::CreateEGLSurfaceForCompositorWidget( EGLNativeWindowType window = GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aCompositorWidget); if (!window) { -#ifdef MOZ_WIDGET_GTK - // RenderCompositorEGL does not like EGL_NO_SURFACE as it fallbacks - // to SW rendering or claims itself as paused. - // In case we're missing valid native window because aCompositorWidget - // hidden, just create a fallback EGLSurface. Actual EGLSurface will be - // created by widget code later when aCompositorWidget becomes visible. - mozilla::gfx::IntSize pbSize(16, 16); -# ifdef MOZ_WAYLAND - if (GdkIsWaylandDisplay()) { - return CreateWaylandOffscreenSurface(*egl, aConfig, pbSize); - } else -# endif - { - return CreatePBufferSurfaceTryingPowerOfTwo(*egl, aConfig, LOCAL_EGL_NONE, - pbSize); - } -#else gfxCriticalNote << "window is null"; return EGL_NO_SURFACE; -#endif } return mozilla::gl::CreateSurfaceFromNativeWindow(*egl, window, aConfig); diff --git a/gfx/layers/wr/WebRenderLayerManager.cpp b/gfx/layers/wr/WebRenderLayerManager.cpp @@ -268,9 +268,8 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) { mDisplayItemCache.SkipWaitingForPartialDisplayList(); - // Don't block on hidden windows on Linux as it may block all rendering. - const bool throttle = mWidget->IsMapped(); - mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(throttle); + mLatestTransactionId = + mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true); if (aFlags & EndTransactionFlags::END_NO_COMPOSITE && !mWebRenderCommandBuilder.NeedsEmptyTransaction()) { @@ -421,9 +420,8 @@ void WebRenderLayerManager::EndTransactionWithoutLayer( // an empty transaction. ClearAndNotifyOfFullTransactionPendingScrollInfoUpdate(); - // Don't block on hidden windows on Linux as it may block all rendering. - const bool throttle = mWidget->IsMapped() && !aRenderOffscreen; - mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(throttle); + mLatestTransactionId = mTransactionIdAllocator->GetTransactionId( + /*aThrottle*/ !aRenderOffscreen); // Get the time of when the refresh driver start its tick (if available), // otherwise use the time of when LayerManager::BeginTransaction was called. diff --git a/gfx/webrender_bindings/RenderCompositorEGL.cpp b/gfx/webrender_bindings/RenderCompositorEGL.cpp @@ -72,6 +72,24 @@ RenderCompositorEGL::RenderCompositorEGL( : RenderCompositor(aWidget), mGL(aGL), mEGLSurface(EGL_NO_SURFACE) { MOZ_ASSERT(mGL); LOG("RenderCompositorEGL::RenderCompositorEGL()"); + +#ifdef MOZ_WIDGET_GTK + mEGLSurface = CreateEGLSurface(); + if (!mEGLSurface) { + RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE); + return; + } + // We have a new EGL surface, which on wayland needs to be configured for + // non-blocking buffer swaps. We need MakeCurrent() to set our current EGL + // context before we call eglSwapInterval, which is why we do it here + // rather than where the surface was created. + const auto& gle = gl::GLContextEGL::Cast(gl()); + const auto& egl = gle->mEgl; + MakeCurrent(); + + const int interval = gfx::gfxVars::SwapIntervalEGL() ? 1 : 0; + egl->fSwapInterval(interval); +#endif } RenderCompositorEGL::~RenderCompositorEGL() { @@ -151,7 +169,7 @@ RenderedFrameId RenderCompositorEGL::EndFrame( gl()->SetDamage(bufferInvalid); } -#ifdef MOZ_WIDGET_GTK +#ifdef MOZ_WAYLAND // Rendering on Wayland has to be atomic (buffer attach + commit) and // wayland surface is also used by main thread so lock it before // we paint at SwapBuffers(). @@ -164,7 +182,11 @@ RenderedFrameId RenderCompositorEGL::EndFrame( return frameId; } -void RenderCompositorEGL::Pause() { DestroyEGLSurface(); } +void RenderCompositorEGL::Pause() { + if (kIsAndroid) { + DestroyEGLSurface(); + } +} bool RenderCompositorEGL::Resume() { if (kIsAndroid) { @@ -202,31 +224,17 @@ bool RenderCompositorEGL::Resume() { mHandlingNewSurfaceError = false; gl::GLContextEGL::Cast(gl())->SetEGLSurfaceOverride(mEGLSurface); - } else if (kIsLinux) { - // Destroy EGLSurface if it exists and create a new one. We will set the - // swap interval after MakeCurrent() has been called. - DestroyEGLSurface(); - mEGLSurface = CreateEGLSurface(); - if (mEGLSurface != EGL_NO_SURFACE) { - // We have a new EGL surface, which on wayland needs to be configured for - // non-blocking buffer swaps. We need MakeCurrent() to set our current EGL - // context before we call eglSwapInterval, which is why we do it here - // rather than where the surface was created. - const auto& gle = gl::GLContextEGL::Cast(gl()); - const auto& egl = gle->mEgl; - MakeCurrent(); - - const int interval = gfx::gfxVars::SwapIntervalEGL() ? 1 : 0; - egl->fSwapInterval(interval); - } else { - RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE); - return false; - } } return true; } -bool RenderCompositorEGL::IsPaused() { return mEGLSurface == EGL_NO_SURFACE; } +bool RenderCompositorEGL::IsPaused() { +#ifdef MOZ_WIDGET_ANDROID + return mEGLSurface == EGL_NO_SURFACE; +#else + return false; +#endif +} bool RenderCompositorEGL::MakeCurrent() { const auto& gle = gl::GLContextEGL::Cast(gl()); diff --git a/gfx/webrender_bindings/RenderCompositorOGLSWGL.cpp b/gfx/webrender_bindings/RenderCompositorOGLSWGL.cpp @@ -218,8 +218,6 @@ bool RenderCompositorOGLSWGL::RequestFullRender() { return mFullRender; } void RenderCompositorOGLSWGL::Pause() { #ifdef MOZ_WIDGET_ANDROID DestroyEGLSurface(); -#elif defined(MOZ_WIDGET_GTK) - mCompositor->Pause(); #endif } @@ -261,12 +259,6 @@ bool RenderCompositorOGLSWGL::Resume() { gl::GLContextEGL::Cast(GetGLContext())->SetEGLSurfaceOverride(mEGLSurface); mCompositor->SetDestinationSurfaceSize(size.ToUnknownSize()); -#elif defined(MOZ_WIDGET_GTK) - bool resumed = mCompositor->Resume(); - if (!resumed) { - RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE); - return false; - } #endif return true; } diff --git a/gfx/webrender_bindings/RenderCompositorSWGL.cpp b/gfx/webrender_bindings/RenderCompositorSWGL.cpp @@ -78,10 +78,8 @@ bool RenderCompositorSWGL::AllocateMappedBuffer( MOZ_ASSERT(!mDT); mDT = mWidget->StartRemoteDrawingInRegion(mDirtyRegion); if (!mDT) { -#if !defined(MOZ_WAYLAND) gfxCriticalNoteOnce << "RenderCompositorSWGL failed mapping default framebuffer, no dt"; -#endif return false; } // Attempt to lock the underlying buffer directly from the draw target. diff --git a/widget/gtk/CompositorWidgetChild.cpp b/widget/gtk/CompositorWidgetChild.cpp @@ -43,9 +43,5 @@ void CompositorWidgetChild::NotifyClientSizeChanged( void CompositorWidgetChild::CleanupResources() { (void)SendCleanupResources(); } -void CompositorWidgetChild::SetRenderingSurface(const uintptr_t aXWindow) { - (void)SendSetRenderingSurface(aXWindow); -} - } // namespace widget } // namespace mozilla diff --git a/widget/gtk/CompositorWidgetChild.h b/widget/gtk/CompositorWidgetChild.h @@ -30,7 +30,6 @@ class CompositorWidgetChild final : public PCompositorWidgetChild, void NotifyClientSizeChanged(const LayoutDeviceIntSize& aClientSize) override; void NotifyFullscreenChanged(bool aIsFullscreen) override {}; void CleanupResources() override; - void SetRenderingSurface(const uintptr_t aXWindow) override; private: ~CompositorWidgetChild() override; diff --git a/widget/gtk/CompositorWidgetParent.cpp b/widget/gtk/CompositorWidgetParent.cpp @@ -44,10 +44,4 @@ mozilla::ipc::IPCResult CompositorWidgetParent::RecvCleanupResources() { return IPC_OK(); } -mozilla::ipc::IPCResult CompositorWidgetParent::RecvSetRenderingSurface( - const uintptr_t& aXWindow) { - SetRenderingSurface(aXWindow); - return IPC_OK(); -} - } // namespace mozilla::widget diff --git a/widget/gtk/CompositorWidgetParent.h b/widget/gtk/CompositorWidgetParent.h @@ -30,8 +30,6 @@ class CompositorWidgetParent final : public PCompositorWidgetParent, const LayoutDeviceIntSize& aClientSize) override; mozilla::ipc::IPCResult RecvCleanupResources() override; - mozilla::ipc::IPCResult RecvSetRenderingSurface( - const uintptr_t& aXWindow) override; private: ~CompositorWidgetParent() override; diff --git a/widget/gtk/GtkCompositorWidget.cpp b/widget/gtk/GtkCompositorWidget.cpp @@ -181,23 +181,6 @@ void GtkCompositorWidget::ConfigureX11Backend(Window aXWindow) { } #endif -void GtkCompositorWidget::SetRenderingSurface(const uintptr_t aXWindow) { - LOG("GtkCompositorWidget::SetRenderingSurface() [%p]\n", mWidget.get()); - -#if defined(MOZ_WAYLAND) - if (GdkIsWaylandDisplay()) { - LOG(" configure widget %p\n", mWidget.get()); - ConfigureWaylandBackend(); - } -#endif -#if defined(MOZ_X11) - if (GdkIsX11Display()) { - LOG(" configure XWindow %p\n", (void*)aXWindow); - ConfigureX11Backend((Window)aXWindow); - } -#endif -} - #ifdef MOZ_LOGGING bool GtkCompositorWidget::IsPopup() { return mWidget ? mWidget->IsPopup() : false; diff --git a/widget/gtk/GtkCompositorWidget.h b/widget/gtk/GtkCompositorWidget.h @@ -32,7 +32,6 @@ class PlatformCompositorWidgetDelegate : public CompositorWidgetDelegate { virtual GtkCompositorWidget* AsGtkCompositorWidget() { return nullptr; }; virtual void CleanupResources() = 0; - virtual void SetRenderingSurface(const uintptr_t aXWindow) = 0; // CompositorWidgetDelegate Overrides @@ -76,9 +75,6 @@ class GtkCompositorWidget : public CompositorWidget, // Can be used when underlying window is hidden/unmapped. void CleanupResources() override; - // Resume rendering with to given aXWindow (X11) or nsWindow (Wayland). - void SetRenderingSurface(const uintptr_t aXWindow) override; - // Set EGLWindow size to avoid rendering artifacts void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize); diff --git a/widget/gtk/PCompositorWidget.ipdl b/widget/gtk/PCompositorWidget.ipdl @@ -23,7 +23,6 @@ parent: async NotifyClientSizeChanged(LayoutDeviceIntSize aClientSize); async CleanupResources(); - async SetRenderingSurface(uintptr_t aXWindow); child: diff --git a/widget/gtk/WindowSurfaceProvider.cpp b/widget/gtk/WindowSurfaceProvider.cpp @@ -11,7 +11,6 @@ #include "mozilla/gfx/Logging.h" #include "mozilla/layers/LayersTypes.h" #include "nsWindow.h" -#include "mozilla/ScopeExit.h" #include "WidgetUtilsGtk.h" #ifdef MOZ_WAYLAND @@ -42,9 +41,7 @@ namespace widget { using namespace mozilla::layers; WindowSurfaceProvider::WindowSurfaceProvider() - : mWindowSurface(nullptr), - mMutex("WindowSurfaceProvider"), - mWindowSurfaceValid(false) + : mWindowSurface(nullptr) #ifdef MOZ_X11 , mXDepth(0), @@ -66,12 +63,10 @@ WindowSurfaceProvider::~WindowSurfaceProvider() { #ifdef MOZ_WAYLAND bool WindowSurfaceProvider::Initialize(RefPtr<nsWindow> aWidget) { - mWindowSurfaceValid = false; mWidget = std::move(aWidget); return true; } bool WindowSurfaceProvider::Initialize(GtkCompositorWidget* aCompositorWidget) { - mWindowSurfaceValid = false; mCompositorWidget = aCompositorWidget; mWidget = static_cast<nsWindow*>(aCompositorWidget->RealWidget()); return true; @@ -79,8 +74,6 @@ bool WindowSurfaceProvider::Initialize(GtkCompositorWidget* aCompositorWidget) { #endif #ifdef MOZ_X11 bool WindowSurfaceProvider::Initialize(Window aWindow) { - mWindowSurfaceValid = false; - // Grab the window's visual and depth XWindowAttributes windowAttrs; if (!XGetWindowAttributes(DefaultXDisplay(), aWindow, &windowAttrs)) { @@ -96,8 +89,6 @@ bool WindowSurfaceProvider::Initialize(Window aWindow) { #endif void WindowSurfaceProvider::CleanupResources() { - MutexAutoLock lock(mMutex); - mWindowSurfaceValid = false; #ifdef MOZ_WAYLAND mWidget = nullptr; #endif @@ -146,11 +137,6 @@ RefPtr<WindowSurface> WindowSurfaceProvider::CreateWindowSurface() { MOZ_RELEASE_ASSERT(false); } -// We need to ignore thread safety checks here. We need to hold mMutex -// between StartRemoteDrawingInRegion()/EndRemoteDrawingInRegion() calls -// which confuses it. -MOZ_PUSH_IGNORE_THREAD_SAFETY - already_AddRefed<gfx::DrawTarget> WindowSurfaceProvider::StartRemoteDrawingInRegion( const LayoutDeviceIntRegion& aInvalidRegion) { @@ -158,19 +144,6 @@ WindowSurfaceProvider::StartRemoteDrawingInRegion( return nullptr; } - // We return a reference to mWindowSurface inside draw target so we need to - // hold the mutex untill EndRemoteDrawingInRegion() call where draw target - // is returned. - // If we return null dt, EndRemoteDrawingInRegion() won't be called to - // release mutex. - mMutex.Lock(); - auto unlockMutex = MakeScopeExit([&] { mMutex.Unlock(); }); - - if (!mWindowSurfaceValid) { - mWindowSurface = nullptr; - mWindowSurfaceValid = true; - } - if (!mWindowSurface) { mWindowSurface = CreateWindowSurface(); if (!mWindowSurface) { @@ -190,37 +163,13 @@ WindowSurfaceProvider::StartRemoteDrawingInRegion( dt = mWindowSurface->Lock(aInvalidRegion); } #endif - if (dt) { - // We have valid dt, mutex will be released in EndRemoteDrawingInRegion(). - unlockMutex.release(); - } - return dt.forget(); } void WindowSurfaceProvider::EndRemoteDrawingInRegion( gfx::DrawTarget* aDrawTarget, const LayoutDeviceIntRegion& aInvalidRegion) { - // Unlock mutex from StartRemoteDrawingInRegion(). - mMutex.AssertCurrentThreadOwns(); - auto unlockMutex = MakeScopeExit([&] { mMutex.Unlock(); }); - - // Commit to mWindowSurface only if we have a valid one. - if (!mWindowSurface || !mWindowSurfaceValid) { - return; - } -#if defined(MOZ_WAYLAND) - if (GdkIsWaylandDisplay()) { - // We're called too early or we're unmapped. - // Don't draw anything. - if (!mWidget || !mWidget->IsMapped()) { - return; - } - } -#endif mWindowSurface->Commit(aInvalidRegion); } -MOZ_POP_THREAD_SAFETY - } // namespace widget } // namespace mozilla diff --git a/widget/gtk/WindowSurfaceProvider.h b/widget/gtk/WindowSurfaceProvider.h @@ -70,16 +70,6 @@ class WindowSurfaceProvider final { RefPtr<WindowSurface> mWindowSurface; - /* While CleanupResources() can be called from Main thread when nsWindow is - * destroyed/hidden, StartRemoteDrawingInRegion()/EndRemoteDrawingInRegion() - * is called from Compositor thread during rendering. - * - * As nsWindow CleanupResources() call comes from Gtk/X11 we can't synchronize - * that with WebRender so we use lock to synchronize the access. - */ - mozilla::Mutex mMutex MOZ_UNANNOTATED; - // WindowSurface needs to be re-created as underlying window was changed. - bool mWindowSurfaceValid; #ifdef MOZ_WAYLAND RefPtr<nsWindow> mWidget; // WindowSurfaceProvider is owned by GtkCompositorWidget so we don't need @@ -88,12 +78,7 @@ class WindowSurfaceProvider final { #endif #ifdef MOZ_X11 int mXDepth; - // Make mXWindow atomic to allow it read from different threads - // and make tsan happy. - // We don't care much about actual mXWindow value (it may be valid XWindow or - // nullptr) because we invalidate mXWindow at compositor/renderer thread - // before it's release in unmap handler. - Atomic<Window, Relaxed> mXWindow; + Window mXWindow; Visual* mXVisual; #endif }; diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp @@ -859,8 +859,6 @@ void nsWindow::SetModal(bool aModal) { // nsIWidget method, which means IsShown. bool nsWindow::IsVisible() const { return mIsShown; } -bool nsWindow::IsMapped() const { return mIsMapped; } - void nsWindow::RegisterTouchWindow() { mHandleTouchEvent = true; mTouches.Clear(); @@ -1398,7 +1396,6 @@ void nsWindow::HideWaylandToplevelWindow() { popup = prev; } } - WaylandStopVsync(); gtk_widget_hide(mShell); } @@ -6082,22 +6079,6 @@ Window nsWindow::GetX11Window() { return (Window) nullptr; } -void nsWindow::ConfigureCompositor() { - LOG("nsWindow::ConfigureCompositor()"); - - if (mIsDestroyed) { - LOG(" quit, mIsDestroyed = %d", !!mIsDestroyed); - return; - } - // Compositor will be resumed at nsWindow::SetCompositorWidgetDelegate(). - if (!mCompositorWidgetDelegate) { - LOG(" quit, missing mCompositorWidgetDelegate"); - return; - } - - ResumeCompositorImpl(); -} - void nsWindow::SetGdkWindow(GdkWindow* aGdkWindow) { LOG("nsWindow::SetGdkWindow() %p", aGdkWindow); if (!aGdkWindow) { @@ -6361,6 +6342,8 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect, } gtk_widget_realize(container); + // mGdkWindow is set by moz_container_realize() / SetGdkWindow(). + MOZ_DIAGNOSTIC_ASSERT(mGdkWindow, "MozContainer realize failed?"); #ifdef MOZ_X11 if (GdkIsX11Display()) { @@ -6369,7 +6352,7 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect, #endif #ifdef MOZ_WAYLAND if (GdkIsWaylandDisplay() && mIsAccelerated) { - mEGLWindow = MOZ_WL_SURFACE(container)->GetEGLWindow(mClientArea.Size()); + mEGLWindow = mSurface->GetEGLWindow(mClientArea.Size()); } #endif if (mEGLWindow) { @@ -6377,6 +6360,24 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect, mGdkWindow, mEGLWindow); } +#ifdef MOZ_X11 + if (GdkIsX11Display()) { + mSurfaceProvider.Initialize(GetX11Window()); + + // Set window manager hint to keep fullscreen windows composited. + // + // If the window were to get unredirected, there could be visible + // tearing because Gecko does not align its framebuffer updates with + // vblank. + SetCompositorHint(GTK_WIDGET_COMPOSITED_ENABLED); + } +#endif +#ifdef MOZ_WAYLAND + if (GdkIsWaylandDisplay()) { + mSurfaceProvider.Initialize(this); + } +#endif + // make sure this is the focus widget in the container gtk_widget_show(container); @@ -6507,6 +6508,7 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect, mWaylandVsyncSource = new WaylandVsyncSource(this); mWaylandVsyncSource->Init(); mWaylandVsyncDispatcher = new VsyncDispatcher(mWaylandVsyncSource); + mWaylandVsyncSource->EnableVSyncSource(); } #endif @@ -6791,44 +6793,6 @@ void nsWindow::NativeMoveResize(bool aMoved, bool aResized) { } } -void nsWindow::ResumeCompositorImpl() { - MOZ_RELEASE_ASSERT(NS_IsMainThread()); - - LOG("nsWindow::ResumeCompositorImpl()\n"); - - MOZ_DIAGNOSTIC_ASSERT(mCompositorWidgetDelegate); - mCompositorWidgetDelegate->SetRenderingSurface(GetX11Window()); - - // As WaylandStartVsync needs mCompositorWidgetDelegate this is the right - // time to start it. - WaylandStartVsync(); - - CompositorBridgeChild* remoteRenderer = GetRemoteRenderer(); - MOZ_RELEASE_ASSERT(remoteRenderer); - remoteRenderer->SendResume(); - remoteRenderer->SendForcePresent(wr::RenderReasons::WIDGET); -} - -void nsWindow::WaylandStartVsync() { -#ifdef MOZ_WAYLAND - if (!mWaylandVsyncSource) { - return; - } - LOG_VSYNC("nsWindow::WaylandStartVsync"); - mWaylandVsyncSource->EnableVSyncSource(); -#endif -} - -void nsWindow::WaylandStopVsync() { -#ifdef MOZ_WAYLAND - if (!mWaylandVsyncSource) { - return; - } - LOG_VSYNC("nsWindow::WaylandStopVsync"); - mWaylandVsyncSource->DisableVSyncSource(); -#endif -} - void nsWindow::NativeShow(bool aAction) { if (aAction) { // unset our flag now that our window has been shown @@ -8933,17 +8897,8 @@ void nsWindow::SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) { delegate, !!mIsMapped, mCompositorWidgetDelegate); MOZ_RELEASE_ASSERT(NS_IsMainThread()); - if (delegate) { - mCompositorWidgetDelegate = delegate->AsPlatformSpecificDelegate(); - MOZ_ASSERT(mCompositorWidgetDelegate, - "nsWindow::SetCompositorWidgetDelegate called with a " - "non-PlatformCompositorWidgetDelegate"); - if (mIsMapped) { - ConfigureCompositor(); - } - } else { - mCompositorWidgetDelegate = nullptr; - } + mCompositorWidgetDelegate = + delegate ? delegate->AsPlatformSpecificDelegate() : nullptr; } bool nsWindow::IsAlwaysUndecoratedWindow() const { @@ -9517,24 +9472,11 @@ nsWindow::GtkWindowDecoration nsWindow::GetSystemGtkWindowDecoration() { void nsWindow::GetCompositorWidgetInitData( mozilla::widget::CompositorWidgetInitData* aInitData) { - nsCString displayName; + MOZ_DIAGNOSTIC_ASSERT(!mIsDestroyed); LOG("nsWindow::GetCompositorWidgetInitData"); - Window window = GetX11Window(); -#ifdef MOZ_X11 - // We're bit hackish here. Old GLX backend needs XWindow when GLContext - // is created so get XWindow now before map signal. - // We may see crashes/errors when nsWindow is unmapped (XWindow is - // invalidated) but we can't do anything about it. - if (!window && !gfxVars::UseEGL()) { - window = - gdk_x11_window_get_xid(gtk_widget_get_window(GTK_WIDGET(mContainer))); - } -#endif - *aInitData = mozilla::widget::GtkCompositorWidgetInitData( - window, displayName, GdkIsX11Display(), GetClientSize()); - + nsCString displayName; #ifdef MOZ_X11 if (GdkIsX11Display()) { // Make sure the window XID is propagated to X server, we can fail otherwise @@ -9544,6 +9486,9 @@ void nsWindow::GetCompositorWidgetInitData( displayName = nsCString(XDisplayString(display)); } #endif + + *aInitData = mozilla::widget::GtkCompositorWidgetInitData( + GetX11Window(), displayName, GdkIsX11Display(), GetClientSize()); } #ifdef MOZ_X11 @@ -9831,24 +9776,6 @@ void nsWindow::OnMap() { if (mIsAlert) { gdk_window_set_override_redirect(GetToplevelGdkWindow(), TRUE); } - -#ifdef MOZ_X11 - if (GdkIsX11Display()) { - mSurfaceProvider.Initialize(GetX11Window()); - - // Set window manager hint to keep fullscreen windows composited. - // - // If the window were to get unredirected, there could be visible - // tearing because Gecko does not align its framebuffer updates with - // vblank. - SetCompositorHint(GTK_WIDGET_COMPOSITED_ENABLED); - } -#endif -#ifdef MOZ_WAYLAND - if (GdkIsWaylandDisplay()) { - mSurfaceProvider.Initialize(this); - } -#endif } if (mIsDragPopup && GdkIsX11Display()) { @@ -9864,12 +9791,7 @@ void nsWindow::OnMap() { RefreshWindowClass(); - // We're not mapped yet but we have already created compositor. - if (mCompositorWidgetDelegate) { - ConfigureCompositor(); - } - - LOG(" finished, new GdkWindow %p XID 0x%lx\n", mGdkWindow, GetX11Window()); + LOG(" finished, GdkWindow %p XID 0x%lx\n", mGdkWindow, GetX11Window()); } void nsWindow::OnUnmap() { diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h @@ -194,7 +194,6 @@ class nsWindow final : public nsIWidget { mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override; void SetModal(bool aModal) override; bool IsVisible() const override; - bool IsMapped() const override; void ConstrainPosition(DesktopIntPoint&) override; void SetSizeConstraints(const SizeConstraints&) override; void LockAspectRatio(bool aShouldLock) override; @@ -531,8 +530,6 @@ class nsWindow final : public nsIWidget { LayoutDeviceIntSize GetMoveToRectPopupSize() override; #endif - void ResumeCompositorImpl(); - bool ApplyEnterLeaveMutterWorkaround(); void NotifyOcclusionState(mozilla::widget::OcclusionState aState) override; @@ -577,8 +574,6 @@ class nsWindow final : public nsIWidget { bool DoTitlebarAction(mozilla::LookAndFeel::TitlebarEvent aEvent, GdkEventButton* aButtonEvent); - void WaylandStartVsync(); - void WaylandStopVsync(); void DestroyChildWindows(); GtkWidget* GetToplevelWidget() const; nsWindow* GetContainerWindow() const; @@ -716,7 +711,7 @@ class nsWindow final : public nsIWidget { // This track real window visibility from OS perspective. // It's set by OnMap/OnUnmap which is based on Gtk events. - mozilla::Atomic<bool, mozilla::Relaxed> mIsMapped; + bool mIsMapped; // Has this widget been destroyed yet? mozilla::Atomic<bool, mozilla::Relaxed> mIsDestroyed; // mIsShown tracks requested visible status from browser perspective, i.e. @@ -871,8 +866,6 @@ class nsWindow final : public nsIWidget { void DispatchMissedButtonReleases(GdkEventCrossing* aGdkEvent); - void ConfigureCompositor(); - bool IsAlwaysUndecoratedWindow() const; // nsIWidget diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h @@ -727,14 +727,6 @@ class nsIWidget : public nsSupportsWeakReference { virtual bool IsVisible() const = 0; /** - * Returns whether the window has allocated resources so - * we can paint into it. - * Recently it's used on Linux/Gtk where we should not paint - * to invisible window. - */ - virtual bool IsMapped() const { return true; } - - /** * Perform platform-dependent sanity check on a potential window position. * This is guaranteed to work only for top-level windows. */