File 0004-egl-swap-provide-damage-rectangles-to-wl_surface.patch of Package libnvidia-egl-wayland

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

openSUSE Build Service is sponsored by