commit e8e17d4083171071da0f32e686942cb525ca42e1
parent ed5d8b39aa223d2c9f083c958bc46d44f884d56d
Author: stransky <stransky@redhat.com>
Date: Wed, 3 Dec 2025 08:32:07 +0000
Bug 2000769 [Wayland] Follow 'stable rounding' algorithm for fractionaly scaled subsurfaces r=emilio
Calculate scaled subsurface size from both position and size as described by:
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/143#note_1343171
which is supposed to be used by all tree major Wayland compositors (Mutter, KWin, WlRoots).
Differential Revision: https://phabricator.services.mozilla.com/D274266
Diffstat:
2 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/widget/gtk/WaylandSurface.cpp b/widget/gtk/WaylandSurface.cpp
@@ -16,6 +16,7 @@
#include "ScreenHelperGTK.h"
#include "DMABufFormats.h"
#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/gfx/Logging.h"
#ifdef MOZ_LOGGING
# include "EncoderConfig.h"
#endif
@@ -92,6 +93,8 @@ WaylandSurface::WaylandSurface(RefPtr<WaylandSurface> aParent)
mParent ? mParent->GetLoggingWidget() : nullptr);
struct wl_compositor* compositor = WaylandDisplayGet()->GetCompositor();
mSurface = wl_compositor_create_surface(compositor);
+ LOGWAYLAND(" created surface %p ID %d", (void*)mSurface,
+ wl_proxy_get_id((struct wl_proxy*)mSurface));
MOZ_RELEASE_ASSERT(mSurface, "Can't create wl_surface!");
}
@@ -464,8 +467,6 @@ bool WaylandSurface::MapLocked(const WaylandSurfaceLock& aProofOfLock,
EnableDMABufFormatsLocked(aProofOfLock, mDMABufFormatRefreshCallback);
}
- LOGWAYLAND(" created surface %p ID %d", (void*)mSurface,
- wl_proxy_get_id((struct wl_proxy*)mSurface));
return true;
}
@@ -952,14 +953,26 @@ bool WaylandSurface::RemoveOpaqueSurfaceHandlerLocked(
return true;
}
+LayoutDeviceIntSize WaylandSurface::GetScaledSize(
+ const DesktopIntSize& aSize) const {
+ DesktopIntRect rect(mSubsurfacePosition, aSize);
+ auto scaledRect =
+ LayoutDeviceIntRect::Round(rect * DesktopToLayoutDeviceScale(GetScale()));
+ LOGVERBOSE(
+ "WaylandSurface::GetScaledSize() pos [%d, %d] size [%d x %d] scale %f "
+ "scaled [%d x %d]",
+ (int)mSubsurfacePosition.x, (int)mSubsurfacePosition.y, aSize.width,
+ aSize.height, GetScale(), scaledRect.width, scaledRect.height);
+ return scaledRect.Size();
+}
+
wl_egl_window* WaylandSurface::GetEGLWindow(DesktopIntSize aSize) {
LOGWAYLAND("WaylandSurface::GetEGLWindow() eglwindow %p", (void*)mEGLWindow);
WaylandSurfaceLock lock(this);
MOZ_DIAGNOSTIC_ASSERT(mSurface, "Missing wl_surface!");
- auto scaledSize = LayoutDeviceIntSize::Round(
- aSize * DesktopToLayoutDeviceScale(GetScale()));
+ auto scaledSize = GetScaledSize(aSize);
if (!mEGLWindow) {
mEGLWindow =
@@ -967,6 +980,10 @@ wl_egl_window* WaylandSurface::GetEGLWindow(DesktopIntSize aSize) {
LOGWAYLAND(
"WaylandSurface::GetEGLWindow() created eglwindow [%p] size %d x %d",
(void*)mEGLWindow, scaledSize.width, scaledSize.height);
+ if (!mEGLWindow) {
+ gfxCriticalError()
+ << "Failed to create EGLWindow - we can't paint anything!";
+ }
} else {
LOGWAYLAND("WaylandSurface::GetEGLWindow() resized to %d x %d",
scaledSize.width, scaledSize.height);
@@ -980,8 +997,7 @@ wl_egl_window* WaylandSurface::GetEGLWindow(DesktopIntSize aSize) {
void WaylandSurface::SetSize(DesktopIntSize aSize) {
WaylandSurfaceLock lock(this);
- auto scaledSize = LayoutDeviceIntSize::Round(
- aSize * DesktopToLayoutDeviceScale(GetScale()));
+ auto scaledSize = GetScaledSize(aSize);
LOGVERBOSE(
"WaylandSurface::SetSize() size [%d x %d] "
@@ -1080,8 +1096,7 @@ bool WaylandSurface::AttachLocked(const WaylandSurfaceLock& aSurfaceLock,
auto scale = GetScale();
LayoutDeviceIntSize bufferSize = aBuffer->GetSize();
- DesktopIntSize surfaceSize((int)round(mSize.width * scale),
- (int)round(mSize.height * scale));
+ auto surfaceSize = GetScaledSize(mSize);
bool sizeMatches = bufferSize.width == surfaceSize.width &&
bufferSize.height == surfaceSize.height;
LOGWAYLAND(
@@ -1182,7 +1197,7 @@ GdkWindow* WaylandSurface::GetGdkWindow() const {
return mGdkWindow;
}
-double WaylandSurface::GetScale() {
+double WaylandSurface::GetScale() const {
#ifdef MOZ_LOGGING
static float lastLoggedScale = 0.0;
#endif
diff --git a/widget/gtk/WaylandSurface.h b/widget/gtk/WaylandSurface.h
@@ -197,7 +197,7 @@ class WaylandSurface final {
// Returns scale as float point number. If WaylandSurface is not mapped,
// return fractional scale of parent surface or monitor.
static constexpr const double sNoScale = -1;
- double GetScale();
+ double GetScale() const;
// Called when screen ceiled scale changed or set initial scale before we map
// and paint the surface.
@@ -301,6 +301,10 @@ class WaylandSurface final {
void ClearScaleLocked(const WaylandSurfaceLock& aProofOfLock);
+ // Calculate 'stable' rounded size for subsurface based
+ // on its size and position.
+ LayoutDeviceIntSize GetScaledSize(const DesktopIntSize& aSize) const;
+
// Weak ref to owning widget (nsWindow or NativeLayerWayland),
// used for diagnostics/logging only.
void* mLoggingWidget = nullptr;
@@ -347,7 +351,7 @@ class WaylandSurface final {
bool mSubsurfaceDesync = true;
wl_subsurface* mSubsurface = nullptr;
- DesktopIntPoint mSubsurfacePosition{-1, -1};
+ DesktopIntPoint mSubsurfacePosition;
// Wayland buffers recently attached to this surface or held by
// Wayland compositor.