libnvidia-egl-wayland/0004-egl-swap-provide-damage-rectangles-to-wl_surface.patch

116 lines
4.7 KiB
Diff

From 8dbdd61b7c07e23bc5b8913fe3d52f32995be98a Mon Sep 17 00:00:00 2001
From: Christian Hergert <chergert@redhat.com>
Date: Fri, 23 Aug 2024 19:10:27 +0200
Subject: [PATCH 4/9] egl-swap: provide damage rectangles to wl_surface
Previously, wlEglSendDamageEvent used the entire surface as damage to
the compositor but in the wrong coordinate system. wl_surface_damage()
requires coordinates for the surface which could be scaled while
wl_surface_damage_buffer() expects buffer coordinates which is what
surface->width and surface->height represent.
This ensures that the parameters to eglSwapBuffersWithDamage() are passed
along to the compositor as well. The coordinate system is flipped between
eglSwapBuffersWithDamage() and wl_surface_damage_buffer() which is handled
as well.
Signed-off-by: Christian Hergert <chergert@redhat.com>
---
include/wayland-eglsurface-internal.h | 4 +++-
src/wayland-eglsurface.c | 25 +++++++++++++++++++++----
src/wayland-eglswap.c | 4 ++--
3 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/include/wayland-eglsurface-internal.h b/include/wayland-eglsurface-internal.h
index dfc5fd4..b70b9d3 100644
--- a/include/wayland-eglsurface-internal.h
+++ b/include/wayland-eglsurface-internal.h
@@ -206,7 +206,9 @@ EGLBoolean
wlEglSurfaceCheckReleasePoints(WlEglDisplay *display, WlEglSurface *surface);
EGLBoolean wlEglSendDamageEvent(WlEglSurface *surface,
- struct wl_event_queue *queue);
+ struct wl_event_queue *queue,
+ EGLint *rects,
+ EGLint n_rects);
void wlEglCreateFrameSync(WlEglSurface *surface);
EGLint wlEglWaitFrameSync(WlEglSurface *surface);
diff --git a/src/wayland-eglsurface.c b/src/wayland-eglsurface.c
index da08fb2..1f01616 100644
--- a/src/wayland-eglsurface.c
+++ b/src/wayland-eglsurface.c
@@ -242,9 +242,13 @@ send_explicit_sync_points (WlEglDisplay *display, WlEglSurface *surface,
}
EGLBoolean
-wlEglSendDamageEvent(WlEglSurface *surface, struct wl_event_queue *queue)
+wlEglSendDamageEvent(WlEglSurface *surface,
+ struct wl_event_queue *queue,
+ EGLint *rects,
+ EGLint n_rects)
{
struct wl_display *wlDpy = surface->wlEglDpy->nativeDpy;
+ EGLint i;
if (surface->ctx.wlStreamResource) {
/* Attach same buffer to indicate new content for the surface is
@@ -286,8 +290,21 @@ wlEglSendDamageEvent(WlEglSurface *surface, struct wl_event_queue *queue)
surface->dy);
}
- wl_surface_damage(surface->wlSurface, 0, 0,
- surface->width, surface->height);
+ if (n_rects > 0 &&
+ (wl_proxy_get_version((struct wl_proxy *)surface->wlSurface) >=
+ WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)) {
+ for (i = 0; i < n_rects; i++) {
+ const EGLint *rect = &rects[i * 4];
+ // Coordinate systems are flipped between eglSwapBuffersWithDamage
+ // and wl_surface_damage_buffer, so invert Y values.
+ int inv_y = surface->height - (rect[1] + rect[3]);
+ wl_surface_damage_buffer(surface->wlSurface, rect[0], inv_y, rect[2], rect[3]);
+ }
+ } else {
+ wl_surface_damage(surface->wlSurface, 0, 0, UINT32_MAX, UINT32_MAX);
+ }
+
+
wl_surface_commit(surface->wlSurface);
surface->ctx.isAttached = EGL_TRUE;
@@ -357,7 +374,7 @@ damage_thread(void *args)
wlEglCreateFrameSync(surface);
- ok = wlEglSendDamageEvent(surface, queue);
+ ok = wlEglSendDamageEvent(surface, queue, NULL, 0);
surface->ctx.framesProcessed++;
pthread_cond_signal(&surface->condFrameSync);
diff --git a/src/wayland-eglswap.c b/src/wayland-eglswap.c
index bf1157d..ea99f49 100644
--- a/src/wayland-eglswap.c
+++ b/src/wayland-eglswap.c
@@ -147,7 +147,7 @@ EGLBoolean wlEglSwapBuffersWithDamageHook(EGLDisplay eglDisplay, EGLSurface eglS
surface->ctx.framesProduced++;
} else {
wlEglCreateFrameSync(surface);
- res = wlEglSendDamageEvent(surface, surface->wlEventQueue);
+ res = wlEglSendDamageEvent(surface, surface->wlEventQueue, rects, n_rects);
wlEglSurfaceCheckReleasePoints(display, surface);
}
}
@@ -434,7 +434,7 @@ EGLBoolean wlEglPostPresentExport2(WlEglSurface *surface,
surface->ctx.framesProduced++;
} else {
wlEglCreateFrameSync(surface);
- res = wlEglSendDamageEvent(surface, surface->wlEventQueue);
+ res = wlEglSendDamageEvent(surface, surface->wlEventQueue, NULL, 0);
}
// Release wlEglSurface lock.
--
2.43.0