commit 4d5f0433ca3f85d0cdae1eef447403e460c4609d
parent 76d5c82cd447eb1132adc893b860d8233de333b2
Author: stransky <stransky@redhat.com>
Date: Mon, 24 Nov 2025 08:34:40 +0000
Bug 1988717 [Wayland] Set WaylandSurface size from nsWindow::DispatchResized() r=emilio
Remove EGLWindow machinery from compositor and set it directly at nsWindow::DispatchResized().
We used to check actual screen scale at compositor if we can paint but as we use viewporter we don't need to any more.
Also use downscaled coordinates to set EGLWindow size to make sure we avoid rounding errors.
Differential Revision: https://phabricator.services.mozilla.com/D273579
Diffstat:
8 files changed, 59 insertions(+), 112 deletions(-)
diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp
@@ -742,15 +742,6 @@ Maybe<IntRect> CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
MakeCurrent(ForceMakeCurrent);
mWidgetSize = LayoutDeviceIntSize::FromUnknownSize(rect.Size());
-#ifdef MOZ_WAYLAND
- if (mWidget && mWidget->AsGTK()) {
- // Wayland only check we have correct window size to avoid
- // rendering artifacts.
- if (!mWidget->AsGTK()->SetEGLNativeWindowSize(mWidgetSize)) {
- return Nothing();
- }
- }
-#endif
} else {
MakeCurrent();
}
diff --git a/gfx/webrender_bindings/RenderCompositorEGL.cpp b/gfx/webrender_bindings/RenderCompositorEGL.cpp
@@ -88,15 +88,7 @@ bool RenderCompositorEGL::BeginFrame() {
<< "We don't have EGLSurface to draw into. Called too early?";
return false;
}
-#ifdef MOZ_WAYLAND
- if (mWidget->AsGTK()) {
- if (!mWidget->AsGTK()->SetEGLNativeWindowSize(GetBufferSize())) {
- // Wayland only check we have correct window size to avoid
- // rendering artifacts.
- return false;
- }
- }
-#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,17 +122,6 @@ EGLNativeWindowType GtkCompositorWidget::GetEGLNativeWindow() {
return window;
}
-bool GtkCompositorWidget::SetEGLNativeWindowSize(
- const LayoutDeviceIntSize& aEGLWindowSize) {
-#if defined(MOZ_WAYLAND)
- // We explicitly need to set EGL window size on Wayland only.
- if (GdkIsWaylandDisplay() && mWidget) {
- return mWidget->SetEGLNativeWindowSize(aEGLWindowSize);
- }
-#endif
- return true;
-}
-
LayoutDeviceIntRegion GtkCompositorWidget::GetTransparentRegion() {
LayoutDeviceIntRegion fullRegion(
LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetClientSize()));
diff --git a/widget/gtk/GtkCompositorWidget.h b/widget/gtk/GtkCompositorWidget.h
@@ -79,10 +79,6 @@ class GtkCompositorWidget : public CompositorWidget,
// Resume rendering with to given aXWindow (X11) or nsWindow (Wayland).
void SetRenderingSurface(const uintptr_t aXWindow) override;
- // If we fail to set window size (due to different screen scale or so)
- // we can't paint the frame by compositor.
- bool 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
@@ -782,12 +782,16 @@ void WaylandSurface::SetCeiledScaleLocked(
}
}
-void WaylandSurface::SetSizeLocked(const WaylandSurfaceLock& aProofOfLock,
- DesktopIntSize aSize) {
+void WaylandSurface::SetRenderingSizeLocked(
+ const WaylandSurfaceLock& aProofOfLock, DesktopIntSize aSize) {
MOZ_DIAGNOSTIC_ASSERT(&aProofOfLock == mSurfaceLock);
- LOGVERBOSE("WaylandSurface::SetSizeLocked(): size [%d x %d]", aSize.width,
- aSize.height);
- if (mViewportFollowsSizeChanges) {
+ 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);
}
}
@@ -960,36 +964,26 @@ wl_egl_window* WaylandSurface::GetEGLWindow(DesktopIntSize aSize) {
wl_egl_window_resize(mEGLWindow, scaledSize.width, scaledSize.height, 0, 0);
}
- if (mEGLWindow) {
- SetSizeLocked(lock, aSize);
- }
-
+ SetRenderingSizeLocked(lock, aSize);
return mEGLWindow;
}
-// Return false if scale factor doesn't match buffer size.
-// We need to skip painting in such case do avoid Wayland compositor freaking.
-bool WaylandSurface::SetEGLWindowSize(LayoutDeviceIntSize aSize) {
+void WaylandSurface::SetSize(DesktopIntSize aSize) {
WaylandSurfaceLock lock(this);
- // We may be called after unmap so we're missing egl window completelly.
- // In such case don't return false which would block compositor.
- // We return true here and don't block flush WebRender queue.
- // We'll be repainted if our window become visible again anyway.
- MOZ_DIAGNOSTIC_ASSERT(mEGLWindow, "Missing ELG window?");
-
- auto unscaledSize =
- DesktopIntSize::Round(aSize / DesktopToLayoutDeviceScale(GetScale()));
+ auto scaledSize = LayoutDeviceIntSize::Round(
+ aSize * DesktopToLayoutDeviceScale(GetScale()));
LOGVERBOSE(
- "WaylandSurface::SetEGLWindowSize() scaled [%d x %d] unscaled [%d x %d] "
- "scale %f",
- aSize.width, aSize.height, unscaledSize.width, unscaledSize.height,
- GetScale());
+ "WaylandSurface::SetSize() size [%d x %d] "
+ "scale %f scaled [%d x %d]",
+ aSize.width, aSize.height, GetScale(), scaledSize.width,
+ scaledSize.height);
- wl_egl_window_resize(mEGLWindow, aSize.width, aSize.height, 0, 0);
- SetSizeLocked(lock, unscaledSize);
- return true;
+ if (mEGLWindow) {
+ wl_egl_window_resize(mEGLWindow, scaledSize.width, scaledSize.height, 0, 0);
+ }
+ SetRenderingSizeLocked(lock, aSize);
}
void WaylandSurface::InvalidateRegionLocked(
@@ -1077,17 +1071,28 @@ bool WaylandSurface::AttachLocked(const WaylandSurfaceLock& aSurfaceLock,
auto scale = GetScale();
LayoutDeviceIntSize bufferSize = aBuffer->GetSize();
-
- // TODO: rounding?
- DesktopIntSize unscaledSize((int)round(bufferSize.width / scale),
- (int)round(bufferSize.height / scale));
- SetSizeLocked(aSurfaceLock, unscaledSize);
-
+ DesktopIntSize surfaceSize((int)round(mSize.width * scale),
+ (int)round(mSize.height * scale));
+ bool sizeMatches = bufferSize.width == surfaceSize.width &&
+ bufferSize.height == surfaceSize.height;
LOGWAYLAND(
"WaylandSurface::AttachLocked() transactions [%d] WaylandBuffer [%p] "
- "attached [%d] size [%d x %d] fractional scale %f",
+ "attached [%d] buffer size [%d x %d] surface (scaled) size [%d x %d] "
+ "fractional scale %f matches %d",
(int)mBufferTransactions.Length(), aBuffer.get(), aBuffer->IsAttached(),
- bufferSize.width, bufferSize.height, scale);
+ bufferSize.width, bufferSize.height, surfaceSize.width,
+ surfaceSize.height, scale, sizeMatches);
+
+ if (mViewportFollowsSizeChanges) {
+ DesktopIntSize viewportSize;
+ if (!sizeMatches) {
+ viewportSize =
+ DesktopIntSize::Round(bufferSize / DesktopToLayoutDeviceScale(scale));
+ } else {
+ viewportSize = mSize;
+ }
+ SetViewPortDestLocked(aSurfaceLock, viewportSize);
+ }
auto* transaction = GetNextTransactionLocked(aSurfaceLock, aBuffer);
if (!transaction) {
@@ -1108,7 +1113,7 @@ void WaylandSurface::RemoveAttachedBufferLocked(
LOGWAYLAND("WaylandSurface::RemoveAttachedBufferLocked()");
- SetSizeLocked(aSurfaceLock, DesktopIntSize(0, 0));
+ SetRenderingSizeLocked(aSurfaceLock, DesktopIntSize());
wl_surface_attach(mSurface, nullptr, 0, 0);
mLatestAttachedBuffer = 0;
mSurfaceNeedsCommit = true;
diff --git a/widget/gtk/WaylandSurface.h b/widget/gtk/WaylandSurface.h
@@ -35,7 +35,7 @@ class WaylandSurface final {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WaylandSurface);
- WaylandSurface(RefPtr<WaylandSurface> aParent);
+ explicit WaylandSurface(RefPtr<WaylandSurface> aParent);
#ifdef MOZ_LOGGING
nsAutoCString GetDebugTag() const;
@@ -68,12 +68,12 @@ class WaylandSurface final {
const WaylandSurfaceLock& aProofOfLock,
const std::function<void(bool)>& aFrameCallbackStateHandler);
- // Create and resize EGL window (Gdk coordinates).
wl_egl_window* GetEGLWindow(DesktopIntSize aSize);
- // Resize EGL window (pixel coordinates).
- bool SetEGLWindowSize(LayoutDeviceIntSize aSize);
bool HasEGLWindow() const { return !!mEGLWindow; }
+ // Set WaylandSurface target size (viewport & ELG surface if it's present).
+ void SetSize(DesktopIntSize aSize);
+
// Mapped means we have all internals created.
bool IsMapped() const { return mIsMapped; }
@@ -279,8 +279,8 @@ class WaylandSurface final {
WaylandSurfaceLock* aParentWaylandSurfaceLock,
DesktopIntPoint aSubsurfacePosition, bool aSubsurfaceDesync);
- void SetSizeLocked(const WaylandSurfaceLock& aProofOfLock,
- DesktopIntSize aSize);
+ void SetRenderingSizeLocked(const WaylandSurfaceLock& aProofOfLock,
+ DesktopIntSize aSize);
wl_surface* Lock(WaylandSurfaceLock* aWaylandSurfaceLock);
void Unlock(struct wl_surface** aSurface,
@@ -318,9 +318,7 @@ class WaylandSurface final {
std::function<void(void)> mGdkCommitCallback;
std::function<void(void)> mUnmapCallback;
- // Scaled surface size, ceiled or fractional.
- // This reflects real surface size which we paint.
- gfx::IntSize mSizeScaled;
+ DesktopIntSize mSize;
// Parent GdkWindow where we paint to, directly or via subsurface.
RefPtr<GdkWindow> mGdkWindow;
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
@@ -590,8 +590,8 @@ void nsWindow::DispatchResized() {
auto clientSize = GetClientSize();
- LOG("nsWindow::DispatchResized() client size [%d, %d]", (int)clientSize.width,
- (int)clientSize.height);
+ LOG("nsWindow::DispatchResized() client scaled size [%d, %d]",
+ (int)clientSize.width, (int)clientSize.height);
// Check out painting texture size
if (mCompositorSession &&
@@ -600,6 +600,14 @@ void nsWindow::DispatchResized() {
<< clientSize << " size state " << mSizeMode;
}
+#ifdef MOZ_WAYLAND
+ if (mSurface) {
+ LOG(" WaylanSurface unscaled size [%d, %d]", mClientArea.Size().width,
+ mClientArea.Size().height);
+ mSurface->SetSize(mClientArea.Size());
+ }
+#endif
+
// Notify the GtkCompositorWidget of a ClientSizeChange
if (mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->NotifyClientSizeChanged(clientSize);
@@ -9883,37 +9891,6 @@ void nsWindow::LockAspectRatio(bool aShouldLock) {
nsWindow* nsWindow::GetFocusedWindow() { return gFocusWindow; }
-#ifdef MOZ_WAYLAND
-bool nsWindow::SetEGLNativeWindowSize(
- const LayoutDeviceIntSize& aEGLWindowSize) {
- // SetEGLNativeWindowSize() is Wayland only call.
- MOZ_ASSERT(GdkIsWaylandDisplay());
-
- if (mIsDestroyed) {
- return true;
- }
-
-# ifdef MOZ_LOGGING
- if (LOG_ENABLED_VERBOSE()) {
- float scale = FractionalScaleFactor();
- static uintptr_t lastSizeLog = 0;
- uintptr_t sizeLog =
- uintptr_t(this) + aEGLWindowSize.width + aEGLWindowSize.height + scale +
- aEGLWindowSize.width / scale + aEGLWindowSize.height / scale;
- if (lastSizeLog != sizeLog) {
- lastSizeLog = sizeLog;
- LOGVERBOSE(
- "nsWindow::SetEGLNativeWindowSize() %d x %d scale %.2f (unscaled "
- "%.2f x %.2f)",
- aEGLWindowSize.width, aEGLWindowSize.height, scale,
- aEGLWindowSize.width / scale, aEGLWindowSize.height / scale);
- }
- }
-# endif
- return mSurface->SetEGLWindowSize(aEGLWindowSize);
-}
-#endif
-
nsWindow* nsWindow::GetWindow(GdkWindow* window) {
return get_window_for_gdk_window(window);
}
diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
@@ -483,7 +483,6 @@ class nsWindow final : public nsIWidget {
static void TransferFocusToWaylandWindow(nsWindow* aWindow);
void FocusWaylandWindow(const char* aTokenID);
- bool SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize);
void WaylandDragWorkaround(GdkEventButton* aEvent);
void CreateCompositorVsyncDispatcher() override;