tor-browser

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

commit 665463a7abfd454454bea8f676dd4a96aee0a92c
parent f0d5ebd81ad267219df0e2d121cd243730828717
Author: Martin Stransky <stransky@redhat.com>
Date:   Fri,  5 Dec 2025 12:48:28 +0000

Bug 2004002 [Wayland] Delay EGL window changes to OpenGL rendering to avoid artifacts r=emilio

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

Diffstat:
Mgfx/layers/opengl/CompositorOGL.cpp | 6++++++
Mgfx/webrender_bindings/RenderCompositorEGL.cpp | 6+++++-
Mwidget/gtk/GtkCompositorWidget.cpp | 10++++++++++
Mwidget/gtk/GtkCompositorWidget.h | 3+++
Mwidget/gtk/WaylandSurface.cpp | 46+++++++++++++++++++++++++++++-----------------
Mwidget/gtk/WaylandSurface.h | 12+++++++++---
Mwidget/gtk/nsWindow.h | 5+++++
7 files changed, 67 insertions(+), 21 deletions(-)

diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp @@ -742,6 +742,12 @@ Maybe<IntRect> CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion, MakeCurrent(ForceMakeCurrent); mWidgetSize = LayoutDeviceIntSize::FromUnknownSize(rect.Size()); +#ifdef MOZ_WAYLAND + if (mWidget && (auto* gtkWidget = mWidget->AsGtk())) { + // Set correct window size to avoid rendering artifacts. + gtkWidget->SetEGLNativeWindowSize(mWidgetSize); + } +#endif } else { MakeCurrent(); } diff --git a/gfx/webrender_bindings/RenderCompositorEGL.cpp b/gfx/webrender_bindings/RenderCompositorEGL.cpp @@ -88,7 +88,11 @@ bool RenderCompositorEGL::BeginFrame() { << "We don't have EGLSurface to draw into. Called too early?"; return false; } - +#ifdef MOZ_WAYLAND + if (auto* gtkWidget = mWidget->AsGtk()) { + gtkWidget->SetEGLNativeWindowSize(GetBufferSize()); + } +#endif if (!MakeCurrent()) { gfxCriticalNote << "Failed to make render context current, can't draw."; return false; diff --git a/widget/gtk/GtkCompositorWidget.cpp b/widget/gtk/GtkCompositorWidget.cpp @@ -122,6 +122,16 @@ EGLNativeWindowType GtkCompositorWidget::GetEGLNativeWindow() { return window; } +void GtkCompositorWidget::SetEGLNativeWindowSize( + const LayoutDeviceIntSize& aEGLWindowSize) { +#if defined(MOZ_WAYLAND) + // We explicitly need to set EGL window size on Wayland only. + if (mWidget && (auto surface = mWidget->GetWaylandSurface())) { + surface->ApplyEGLWindowSize(aEGLWindowSize); + } +#endif +} + LayoutDeviceIntRegion GtkCompositorWidget::GetTransparentRegion() { LayoutDeviceIntRegion fullRegion( LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetClientSize())); diff --git a/widget/gtk/GtkCompositorWidget.h b/widget/gtk/GtkCompositorWidget.h @@ -79,6 +79,9 @@ class GtkCompositorWidget : public CompositorWidget, // 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); + #if defined(MOZ_X11) Window XWindow() const { return mProvider.GetXWindow(); } #endif diff --git a/widget/gtk/WaylandSurface.cpp b/widget/gtk/WaylandSurface.cpp @@ -792,20 +792,6 @@ void WaylandSurface::SetCeiledScaleLocked( } } -void WaylandSurface::SetRenderingSizeLocked( - const WaylandSurfaceLock& aProofOfLock, DesktopIntSize aSize) { - MOZ_DIAGNOSTIC_ASSERT(&aProofOfLock == mSurfaceLock); - LOGVERBOSE("WaylandSurface::SetRenderingSizeLocked(): size [%d x %d]", - aSize.width, aSize.height); - mSize = aSize; - - // non-EGL rendering changes are applied at WaylandSurface::AttachLocked(). - // We want to sync size changes with matching buffer. - if (mViewportFollowsSizeChanges && mEGLWindow) { - SetViewPortDestLocked(aProofOfLock, aSize); - } -} - void WaylandSurface::SetViewPortDestLocked( const WaylandSurfaceLock& aProofOfLock, DesktopIntSize aDestSize) { MOZ_DIAGNOSTIC_ASSERT(&aProofOfLock == mSurfaceLock); @@ -972,6 +958,7 @@ wl_egl_window* WaylandSurface::GetEGLWindow(DesktopIntSize aSize) { WaylandSurfaceLock lock(this); MOZ_DIAGNOSTIC_ASSERT(mSurface, "Missing wl_surface!"); + mSize = aSize; auto scaledSize = GetScaledSize(aSize); if (!mEGLWindow) { @@ -990,13 +977,13 @@ wl_egl_window* WaylandSurface::GetEGLWindow(DesktopIntSize aSize) { wl_egl_window_resize(mEGLWindow, scaledSize.width, scaledSize.height, 0, 0); } - SetRenderingSizeLocked(lock, aSize); return mEGLWindow; } void WaylandSurface::SetSize(DesktopIntSize aSize) { WaylandSurfaceLock lock(this); + mSize = aSize; auto scaledSize = GetScaledSize(aSize); LOGVERBOSE( @@ -1004,11 +991,36 @@ void WaylandSurface::SetSize(DesktopIntSize aSize) { "scale %f scaled [%d x %d]", aSize.width, aSize.height, GetScale(), scaledSize.width, scaledSize.height); +} + +void WaylandSurface::ApplyEGLWindowSize(LayoutDeviceIntSize aEGLWindowSize) { + WaylandSurfaceLock lock(this); + + auto scale = GetScale(); + auto surfaceSize = GetScaledSize(mSize); + bool sizeMatches = aEGLWindowSize == surfaceSize; + LOGWAYLAND( + "WaylandSurface::ApplyEGLWindowSize()" + " EGL window size [%d x %d] surface (scaled) size [%d x %d] " + "fractional scale %f matches %d", + aEGLWindowSize.width, aEGLWindowSize.height, surfaceSize.width, + surfaceSize.height, scale, sizeMatches); + + if (mViewportFollowsSizeChanges) { + DesktopIntSize viewportSize; + if (!sizeMatches) { + viewportSize = DesktopIntSize::Round(aEGLWindowSize / + DesktopToLayoutDeviceScale(scale)); + } else { + viewportSize = mSize; + } + SetViewPortDestLocked(lock, viewportSize); + } if (mEGLWindow) { - wl_egl_window_resize(mEGLWindow, scaledSize.width, scaledSize.height, 0, 0); + wl_egl_window_resize(mEGLWindow, aEGLWindowSize.width, + aEGLWindowSize.height, 0, 0); } - SetRenderingSizeLocked(lock, aSize); } void WaylandSurface::InvalidateRegionLocked( diff --git a/widget/gtk/WaylandSurface.h b/widget/gtk/WaylandSurface.h @@ -74,6 +74,15 @@ class WaylandSurface final { // Set WaylandSurface target size (viewport & ELG surface if it's present). void SetSize(DesktopIntSize aSize); + // Apply changes to EGLWindow size set by SetSize(). + // ApplyEGLWindowSize() is called from compostor thread + // right before GL rendering to set EGLWindow size / viewport size + // for actual back buffer. + // + // aEGLWindowSize is scaled backbuffer size and it's used similary + // as WaylandBuffer size at Attach(). + void ApplyEGLWindowSize(LayoutDeviceIntSize aEGLWindowSize); + // Mapped means we have all internals created. bool IsMapped() const { return mIsMapped; } @@ -279,9 +288,6 @@ class WaylandSurface final { WaylandSurfaceLock* aParentWaylandSurfaceLock, DesktopIntPoint aSubsurfacePosition, bool aSubsurfaceDesync); - void SetRenderingSizeLocked(const WaylandSurfaceLock& aProofOfLock, - DesktopIntSize aSize); - wl_surface* Lock(WaylandSurfaceLock* aWaylandSurfaceLock); void Unlock(struct wl_surface** aSurface, WaylandSurfaceLock* aWaylandSurfaceLock); diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h @@ -345,6 +345,11 @@ class nsWindow final : public nsIWidget { GdkWindow* GetToplevelGdkWindow() const; GtkWidget* GetGtkWidget() const { return mShell; } nsWindow* GetEffectiveParent(); +#ifdef MOZ_WAYLAND + RefPtr<mozilla::widget::WaylandSurface> GetWaylandSurface() { + return mSurface; + } +#endif bool IsDestroyed() const { return mIsDestroyed; } bool IsPopup() const; bool IsWaylandPopup() const;