xserver: Branch 'xwayland-23.2' - 12 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jul 28 06:44:55 UTC 2023


 glamor/glamor_compositerects.c |    8 +--
 glamor/glamor_copy.c           |    8 +--
 glamor/glamor_image.c          |    2 
 glamor/glamor_prepare.c        |    4 -
 glamor/glamor_priv.h           |   26 +++++++++
 glamor/glamor_render.c         |    2 
 glamor/glamor_text.c           |    7 --
 glamor/glamor_transfer.c       |    2 
 glamor/glamor_transform.h      |    3 -
 glamor/glamor_utils.c          |    3 -
 hw/xwayland/xwayland-glamor.c  |  109 +++++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland-screen.c  |    1 
 hw/xwayland/xwayland-screen.h  |    2 
 hw/xwayland/xwayland-window.c  |   87 +++++++++++++++++++++++---------
 mi/miexpose.c                  |   24 +++++++++
 15 files changed, 240 insertions(+), 48 deletions(-)

New commits:
commit 5b39ad9041d22a34a0af00d14697d7fe82c4fc26
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jul 25 16:25:29 2023 +0200

    xwayland: Make fullscreen used a fixed size
    
    Similar to commit 94deed272 - " xwayland: Use sensible defaults for
    rootful size", mark fullscreen mode as fixed so that the actual monitor
    layout is not reflected in the single fullscreen rootful window.
    
    Without this, if "-fullscreen" is used without "-geometry", the XRandR
    configuration is taken from the compositor via wl_output/xdg-output and
    cannot be changed by the X11 clients.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit 34446a99528a9c2ee1cc5e83118e5d0c58795b31)

diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index 37ee7da0f..6b57fbe9d 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -799,6 +799,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
             use_fixed_size = 1;
         }
         else if (strcmp(argv[i], "-fullscreen") == 0) {
+            use_fixed_size = 1;
             xwl_screen->fullscreen = 1;
         }
         else if (strcmp(argv[i], "-host-grab") == 0) {
commit 9b6b11d194593942bccea2963df8fbac1ae6bdc5
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Mon Jul 24 17:39:51 2023 +0200

    xwayland: Set min/max size for rootful with lidecor
    
    Enforce sensible min/max values for the window size when using libdecor.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit 881e1a569393aae3010a17079567be47c70d259e)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 1766c48af..f1d6580e6 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -53,6 +53,11 @@
 
 #define DELAYED_WL_SURFACE_DESTROY 1000 /* ms */
 
+#define MAX_ROOTFUL_WIDTH 32767
+#define MAX_ROOTFUL_HEIGHT 32767
+#define MIN_ROOTFUL_WIDTH 320
+#define MIN_ROOTFUL_HEIGHT 200
+
 static DevPrivateKeyRec xwl_window_private_key;
 static DevPrivateKeyRec xwl_damage_private_key;
 static const char *xwl_surface_tag = "xwl-surface";
@@ -604,6 +609,15 @@ xwl_window_rootful_set_app_id(struct xwl_window *xwl_window)
 }
 
 #ifdef XWL_HAS_LIBDECOR
+static void
+xwl_window_libdecor_set_size_limits(struct xwl_window *xwl_window)
+{
+    libdecor_frame_set_min_content_size(xwl_window->libdecor_frame,
+                                        MIN_ROOTFUL_WIDTH, MIN_ROOTFUL_HEIGHT);
+    libdecor_frame_set_max_content_size(xwl_window->libdecor_frame,
+                                        MAX_ROOTFUL_WIDTH, MAX_ROOTFUL_HEIGHT);
+}
+
 static void
 xwl_window_update_libdecor_size(struct xwl_window *xwl_window,
                                 struct libdecor_configuration *configuration /* nullable */,
@@ -649,6 +663,9 @@ handle_libdecor_configure(struct libdecor_frame *frame,
         width = xwl_screen->width;
         height = xwl_screen->height;
     }
+    /* Clamp the size */
+    width = min(max(width, MIN_ROOTFUL_WIDTH), MAX_ROOTFUL_WIDTH);
+    height = min(max(height, MIN_ROOTFUL_HEIGHT), MAX_ROOTFUL_HEIGHT) ;
 
     if (xwl_screen->width != width || xwl_screen->height != height)
         xwl_window_libdecor_resize(xwl_window, width, height);
@@ -776,6 +793,7 @@ xwl_create_root_surface(struct xwl_window *xwl_window)
                               xwl_window->surface,
                               &libdecor_frame_iface,
                               xwl_window);
+        xwl_window_libdecor_set_size_limits(xwl_window);
         libdecor_frame_map(xwl_window->libdecor_frame);
     }
     else
@@ -808,7 +826,6 @@ xwl_create_root_surface(struct xwl_window *xwl_window)
 
     xwl_window_rootful_update_title(xwl_window);
     xwl_window_rootful_set_app_id(xwl_window);
-
     wl_surface_commit(xwl_window->surface);
 
     region = wl_compositor_create_region(xwl_screen->compositor);
commit 6be0ac85f4f4c5b165425f124ff956fa16ea5d04
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Jul 26 09:36:17 2023 +0200

    xwayland: Use update size from libdecor configure handler
    
    This is to avoid repeating the same code in two places.
    
    This is essentially a cosmetic change, not a functional change.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit f19fe9d260cfc3e4e2991393bf9339caba8b7a5a)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 985b0f14a..1766c48af 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -643,7 +643,6 @@ handle_libdecor_configure(struct libdecor_frame *frame,
 {
     struct xwl_window *xwl_window = data;
     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
-    struct libdecor_state *state;
     int width, height;
 
     if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
@@ -654,9 +653,8 @@ handle_libdecor_configure(struct libdecor_frame *frame,
     if (xwl_screen->width != width || xwl_screen->height != height)
         xwl_window_libdecor_resize(xwl_window, width, height);
 
-    state = libdecor_state_new(xwl_screen->width, xwl_screen->height);
-    libdecor_frame_commit(frame, state, configuration);
-    libdecor_state_free(state);
+    xwl_window_update_libdecor_size(xwl_window, configuration,
+                                    xwl_screen->width, xwl_screen->height);
 }
 
 static void
commit 7c04404d770f833ad41beceb0ec4fce191a1dbae
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Jul 26 09:34:18 2023 +0200

    xwayland: Add configuration to libdecor update size
    
    Allow passing an optional libdecor configuration pointer to
    xwl_window_update_libdecor_size() so that we can reuse it from more than
    one place and avoid duplicating that code.
    
    No functional change.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit c180eca8ef71e42a9bea23ae276c24d97caf4577)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 0951e47cd..985b0f14a 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -605,13 +605,15 @@ xwl_window_rootful_set_app_id(struct xwl_window *xwl_window)
 
 #ifdef XWL_HAS_LIBDECOR
 static void
-xwl_window_update_libdecor_size(struct xwl_window *xwl_window, int width, int height)
+xwl_window_update_libdecor_size(struct xwl_window *xwl_window,
+                                struct libdecor_configuration *configuration /* nullable */,
+                                int width, int height)
 {
     struct libdecor_state *state;
 
     if (xwl_window->libdecor_frame) {
 	state = libdecor_state_new(width, height);
-	libdecor_frame_commit(xwl_window->libdecor_frame, state, NULL);
+	libdecor_frame_commit(xwl_window->libdecor_frame, state, configuration);
 	libdecor_state_free(state);
     }
 }
@@ -1226,7 +1228,7 @@ xwl_resize_window(WindowPtr window,
             xwl_window_check_resolution_change_emulation(xwl_window);
 #ifdef XWL_HAS_LIBDECOR
         if (window == screen->root)
-            xwl_window_update_libdecor_size(xwl_window, width, height);
+            xwl_window_update_libdecor_size(xwl_window, NULL, width, height);
 #endif
     }
 }
commit c728d29127078dc84f37050d267c376ad97174e0
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Mon Jul 24 17:03:56 2023 +0200

    xwayland: attach new buffer from libdecor handlers
    
    The configure handler in libdecor is triggered any time a new
    configuration is received.
    
    According to the documentation from libdecor, an application should
    respond to that event by creating a suitable libdecor_state, and apply
    it using libdecor_frame_commit().
    
    So we ought to attach a new buffer matching the new size and commit
    the Wayland surface.
    
    The actual content of the window does not need to be explicitly
    repainted, that occurs through the call to SetRootClip():
    
      xwl_output_set_mode_fixed()
      -> update_screen_size()
         -> SetRootClip()
            -> miHandleValidateExposures()
               -> miWindowExposures()
                  -> miPaintWindow()
    
    This fixes an issue with mutter where maximizing a window and then
    switching to another window would sometimes resize the Xwayland window
    back to its pre-maximized size, or with Weston where the Xwayland window
    would initially show up black until the pointer moves to the window.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit 6d00c2bc1077c9e1e870303b1b49ec694089fc4e)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 72c832e4e..0951e47cd 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -629,6 +629,9 @@ xwl_window_libdecor_resize(struct xwl_window *xwl_window, int width, int height)
 
     mode = xwl_output_find_mode(xwl_output, width, height);
     xwl_output_set_mode_fixed(xwl_output, mode);
+
+    xwl_window_attach_buffer(xwl_window);
+    wl_surface_commit(xwl_window->surface);
 }
 
 static void
@@ -652,8 +655,6 @@ handle_libdecor_configure(struct libdecor_frame *frame,
     state = libdecor_state_new(xwl_screen->width, xwl_screen->height);
     libdecor_frame_commit(frame, state, configuration);
     libdecor_state_free(state);
-
-    wl_surface_commit(xwl_window->surface);
 }
 
 static void
commit 37864d77ee9632357790548e8854d1a8a56c3f26
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jul 25 18:38:24 2023 +0200

    xwayland: Move the libdecor resize to its own function
    
    This moves the code which updates the XRandR modes and sets the root
    window size to its own function.
    
    This preparation work for the next commit, no functional change.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit e37539e1e2d38127fc7ae600da543b0ac341ec14)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 85d917161..72c832e4e 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -616,6 +616,21 @@ xwl_window_update_libdecor_size(struct xwl_window *xwl_window, int width, int he
     }
 }
 
+static void
+xwl_window_libdecor_resize(struct xwl_window *xwl_window, int width, int height)
+{
+    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+    struct xwl_output *xwl_output;
+    RRModePtr mode;
+
+    xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen);
+    if (!xwl_randr_add_modes_fixed(xwl_output, width, height))
+        return;
+
+    mode = xwl_output_find_mode(xwl_output, width, height);
+    xwl_output_set_mode_fixed(xwl_output, mode);
+}
+
 static void
 handle_libdecor_configure(struct libdecor_frame *frame,
                           struct libdecor_configuration *configuration,
@@ -623,9 +638,7 @@ handle_libdecor_configure(struct libdecor_frame *frame,
 {
     struct xwl_window *xwl_window = data;
     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
-    struct xwl_output *xwl_output;
     struct libdecor_state *state;
-    RRModePtr mode;
     int width, height;
 
     if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
@@ -633,13 +646,8 @@ handle_libdecor_configure(struct libdecor_frame *frame,
         height = xwl_screen->height;
     }
 
-    if (xwl_screen->width != width || xwl_screen->height != height) {
-        xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen);
-        if (xwl_randr_add_modes_fixed(xwl_output, width, height)) {
-            mode = xwl_output_find_mode(xwl_output, width, height);
-            xwl_output_set_mode_fixed(xwl_output, mode);
-        }
-    }
+    if (xwl_screen->width != width || xwl_screen->height != height)
+        xwl_window_libdecor_resize(xwl_window, width, height);
 
     state = libdecor_state_new(xwl_screen->width, xwl_screen->height);
     libdecor_frame_commit(frame, state, configuration);
commit 5d41621ed90c62724e6d8c9f9d3ddc694c1d7a6f
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Thu Jul 27 08:49:19 2023 +0200

    xwayland: Use the screen width/height for libdecor state
    
    The configure handler for libdecor, namely handle_libdecor_configure(),
    is where both the content and the decorations get resized (when needed).
    
    If for any reason, the actual size of the Xwayland screen fails to be
    updated, we would still appy the expected size rather than the actual
    one for the libdecor state.
    
    To avoid this, use the actual xwl_screen width/height for the libdecor
    state.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit cda004c2a9d7ae585e9284c1989333297fbaeede)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 5707e3bfe..85d917161 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -641,7 +641,7 @@ handle_libdecor_configure(struct libdecor_frame *frame,
         }
     }
 
-    state = libdecor_state_new(width, height);
+    state = libdecor_state_new(xwl_screen->width, xwl_screen->height);
     libdecor_frame_commit(frame, state, configuration);
     libdecor_state_free(state);
 
commit 992d344d8f08b0f91d8c4f7127e8cdc197e8c5e8
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Mon Jul 24 16:39:03 2023 +0200

    xwayland: Move attach buffer out of post damage
    
    For libdecor, we will have to attach a new buffer and commit from two
    different handlers (libdecor configure and commit).
    
    Having xwl_window_attach_buffer() separate from xwl_window_post_damage()
    is to allow for that.
    
    This commit should not introduce any functional change.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit 8bbd908d1d8512825983322ab7a0eadcf6571131)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index a58a4439a..5707e3bfe 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -57,6 +57,8 @@ static DevPrivateKeyRec xwl_window_private_key;
 static DevPrivateKeyRec xwl_damage_private_key;
 static const char *xwl_surface_tag = "xwl-surface";
 
+static Bool xwl_window_attach_buffer(struct xwl_window *);
+
 struct xwl_window *
 xwl_window_get(WindowPtr window)
 {
@@ -1312,8 +1314,8 @@ xwl_destroy_window(WindowPtr window)
     return ret;
 }
 
-void
-xwl_window_post_damage(struct xwl_window *xwl_window)
+static Bool
+xwl_window_attach_buffer(struct xwl_window *xwl_window)
 {
     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
     RegionPtr region;
@@ -1322,8 +1324,6 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
     PixmapPtr pixmap;
     int i;
 
-    assert(!xwl_window->frame_callback);
-
     region = DamageRegion(window_get_damage(xwl_window->window));
     pixmap = xwl_window_buffers_get_pixmap(xwl_window, region);
 
@@ -1336,14 +1336,14 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
 
     if (!buffer) {
         ErrorF("Error getting buffer\n");
-        return;
+        return FALSE;
     }
 
 #ifdef XWL_HAS_GLAMOR
     if (xwl_screen->glamor) {
         if (!xwl_glamor_post_damage(xwl_window, pixmap, region)) {
             ErrorF("glamor: Failed to post damage\n");
-            return;
+            return FALSE;
         }
     }
 #endif
@@ -1370,6 +1370,17 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
         }
     }
 
+    return TRUE;
+}
+
+void
+xwl_window_post_damage(struct xwl_window *xwl_window)
+{
+    assert(!xwl_window->frame_callback);
+
+    if (!xwl_window_attach_buffer(xwl_window))
+        return;
+
     xwl_window_create_frame_callback(xwl_window);
     DamageEmpty(window_get_damage(xwl_window->window));
 }
commit b3ee500224049c8cdaf80b3104f94990b87129a6
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Thu Jul 20 10:15:15 2023 +0200

    xwayland/glamor: Avoid implicit redirection with depth 32 parent windows
    
    glamor ensures that a depth 32 pixmap backing a depth 24 window contains
    fully opaque alpha channel values for the window's pixels, so we can
    allow this without implicit redirection, saving pixmap storage and
    intermediate copies.
    
    Second attempt, after fixing a few regressions from the first attempt.
    
    (cherry picked from commit 4bb1f976d5397949be06510524bede5ae3bbfe0a)

diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 9ac1aa8d4..c6aa8eb17 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -25,6 +25,8 @@
 
 #include <xwayland-config.h>
 
+#include <compositeext.h>
+
 #define MESA_EGL_NO_X11_HEADERS
 #define EGL_NO_X11
 #include <glamor_egl.h>
@@ -893,6 +895,108 @@ xwl_glamor_allow_commits(struct xwl_window *xwl_window)
         return TRUE;
 }
 
+static void
+xwl_avoid_implicit_redirect(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    WindowOptPtr parent_optional;
+    VisualPtr parent_visual = NULL;
+    VisualPtr window_visual = NULL;
+    DepthPtr depth32 = NULL;
+    int i;
+
+    if (!window->optional)
+        return;
+
+    parent_optional = FindWindowWithOptional(window)->optional;
+    if (window->optional == parent_optional ||
+        window->optional->visual == parent_optional->visual ||
+        CompositeIsImplicitRedirectException(screen, parent_optional->visual,
+                                             window->optional->visual))
+        return;
+
+    for (i = 0; i < screen->numDepths; i++) {
+        if (screen->allowedDepths[i].depth == 32) {
+            depth32 = &screen->allowedDepths[i];
+            break;
+        }
+    }
+
+    if (!depth32)
+        return;
+
+    for (i = 0; i < depth32->numVids; i++) {
+        XID argb_vid = depth32->vids[i];
+
+        if (argb_vid != parent_optional->visual)
+            continue;
+
+        if (!compIsAlternateVisual(screen, argb_vid))
+            break;
+
+        for (i = 0; i < screen->numVisuals; i++) {
+            if (screen->visuals[i].vid == argb_vid) {
+                parent_visual = &screen->visuals[i];
+                break;
+            }
+        }
+    }
+
+    if (!parent_visual)
+        return;
+
+    for (i = 0; i < screen->numVisuals; i++) {
+        if (screen->visuals[i].vid == window->optional->visual) {
+            window_visual = &screen->visuals[i];
+            break;
+        }
+    }
+
+    if ((window_visual->class != TrueColor &&
+         window_visual->class != DirectColor) ||
+        window_visual->redMask != parent_visual->redMask ||
+        window_visual->greenMask != parent_visual->greenMask ||
+        window_visual->blueMask != parent_visual->blueMask ||
+        window_visual->offsetRed != parent_visual->offsetRed ||
+        window_visual->offsetGreen != parent_visual->offsetGreen ||
+        window_visual->offsetBlue != parent_visual->offsetBlue)
+        return;
+
+    CompositeRegisterImplicitRedirectionException(screen, parent_visual->vid, window_visual->vid);
+}
+
+static Bool
+xwl_glamor_create_window(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    Bool ret;
+
+    if (window->parent)
+        xwl_avoid_implicit_redirect(window);
+
+    screen->CreateWindow = xwl_screen->CreateWindow;
+    ret = (*screen->CreateWindow) (window);
+    xwl_screen->CreateWindow = screen->CreateWindow;
+    screen->CreateWindow = xwl_glamor_create_window;
+
+    return ret;
+}
+
+static void
+xwl_glamor_reparent_window(WindowPtr window, WindowPtr old_parent)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+
+    xwl_avoid_implicit_redirect(window);
+
+    screen->ReparentWindow = xwl_screen->ReparentWindow;
+    (*screen->ReparentWindow) (window, old_parent);
+    xwl_screen->ReparentWindow = screen->ReparentWindow;
+    screen->ReparentWindow = xwl_glamor_reparent_window;
+}
+
 static Bool
 xwl_glamor_create_screen_resources(ScreenPtr screen)
 {
@@ -907,6 +1011,11 @@ xwl_glamor_create_screen_resources(ScreenPtr screen)
     if (!ret)
         return ret;
 
+    xwl_screen->CreateWindow = screen->CreateWindow;
+    screen->CreateWindow = xwl_glamor_create_window;
+    xwl_screen->ReparentWindow = screen->ReparentWindow;
+    screen->ReparentWindow = xwl_glamor_reparent_window;
+
     if (xwl_screen->rootless) {
         screen->devPrivate =
             fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index da97d7f1d..94033aabf 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -70,12 +70,14 @@ struct xwl_screen {
 
     CreateScreenResourcesProcPtr CreateScreenResources;
     CloseScreenProcPtr CloseScreen;
+    CreateWindowProcPtr CreateWindow;
     RealizeWindowProcPtr RealizeWindow;
     UnrealizeWindowProcPtr UnrealizeWindow;
     DestroyWindowProcPtr DestroyWindow;
     XYToWindowProcPtr XYToWindow;
     SetWindowPixmapProcPtr SetWindowPixmap;
     ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+    ReparentWindowProcPtr ReparentWindow;
     ResizeWindowProcPtr ResizeWindow;
     MoveWindowProcPtr MoveWindow;
 
commit d82d2c96dc71ab8e60e730cf03762ba86680b961
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Wed Jul 19 18:00:18 2023 +0200

    glamor: Make glamor_solid_boxes take a DrawablePtr
    
    Instead of a PixmapPtr. Gives better results if the window depth
    doesn't match the backing pixmap depth.
    
    Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1565
    (cherry picked from commit d4e11f4c922a119dfb5130b15ac22f58589783e7)

diff --git a/glamor/glamor_compositerects.c b/glamor/glamor_compositerects.c
index 199e62705..0796fed41 100644
--- a/glamor/glamor_compositerects.c
+++ b/glamor/glamor_compositerects.c
@@ -227,12 +227,10 @@ glamor_composite_rectangles(CARD8 op,
     boxes = pixman_region_rectangles(&region, &num_boxes);
     if (op == PictOpSrc || op == PictOpClear) {
         CARD32 pixel;
-        int dst_x, dst_y;
 
-        glamor_get_drawable_deltas(dst->pDrawable, pixmap, &dst_x, &dst_y);
-        pixman_region_translate(&region, dst_x, dst_y);
+        pixman_region_translate(&region, -dst->pDrawable->x, -dst->pDrawable->y);
 
-        DEBUGF("%s: pixmap +(%d, %d) extents (%d, %d),(%d, %d)\n",
+        DEBUGF("%s: drawable extents (%d, %d),(%d, %d)\n",
                __FUNCTION__, dst_x, dst_y,
                RegionExtents(&region)->x1, RegionExtents(&region)->y1,
                RegionExtents(&region)->x2, RegionExtents(&region)->y2);
@@ -241,7 +239,7 @@ glamor_composite_rectangles(CARD8 op,
             pixel = 0;
         else
             miRenderColorToPixel(dst->pFormat, color, &pixel);
-        glamor_solid_boxes(pixmap, boxes, num_boxes, pixel);
+        glamor_solid_boxes(dst->pDrawable, boxes, num_boxes, pixel);
 
         goto done;
     }
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 2f787015d..898380d82 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -895,7 +895,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
              unsigned long fg_pixel);
 
 void
-glamor_solid_boxes(PixmapPtr pixmap,
+glamor_solid_boxes(DrawablePtr drawable,
                    BoxPtr box, int nbox, unsigned long fg_pixel);
 
 
diff --git a/glamor/glamor_text.c b/glamor/glamor_text.c
index a559aea8a..5343cc93b 100644
--- a/glamor/glamor_text.c
+++ b/glamor/glamor_text.c
@@ -432,7 +432,6 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
         int c;
         RegionRec region;
         BoxRec box;
-        int off_x, off_y;
 
         /* Check planemask before drawing background to
          * bail early if it's not OK
@@ -443,8 +442,6 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
             if (charinfo[c])
                 width += charinfo[c]->metrics.characterWidth;
 
-        glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
-
         if (width >= 0) {
             box.x1 = drawable->x + x;
             box.x2 = drawable->x + x + width;
@@ -456,8 +453,8 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
         box.y2 = drawable->y + y + gc->font->info.fontDescent;
         RegionInit(&region, &box, 1);
         RegionIntersect(&region, &region, gc->pCompositeClip);
-        RegionTranslate(&region, off_x, off_y);
-        glamor_solid_boxes(pixmap, RegionRects(&region), RegionNumRects(&region), gc->bgPixel);
+        RegionTranslate(&region, -drawable->x, -drawable->y);
+        glamor_solid_boxes(drawable, RegionRects(&region), RegionNumRects(&region), gc->bgPixel);
         RegionUninit(&region);
     }
 
diff --git a/glamor/glamor_utils.c b/glamor/glamor_utils.c
index d3e6fd3ff..8f085da3f 100644
--- a/glamor/glamor_utils.c
+++ b/glamor/glamor_utils.c
@@ -23,10 +23,9 @@
 #include "glamor_priv.h"
 
 void
-glamor_solid_boxes(PixmapPtr pixmap,
+glamor_solid_boxes(DrawablePtr drawable,
                    BoxPtr box, int nbox, unsigned long fg_pixel)
 {
-    DrawablePtr drawable = &pixmap->drawable;
     GCPtr gc;
     xRectangle *rect;
     int n;
commit 6ed8c959657dde9ad9e2531708918d26cea7535c
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Wed Jul 19 10:43:56 2023 +0200

    mi: Fix up alpha channel if needed in miPaintWindow
    
    See also the previous commit log.
    
    Fixes the issues with xterm & xcalc described in the GitLab issue below.
    
    Issue: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1564
    (cherry picked from commit 2de50de563df9d2315d74a63ce5ffbaf3c25f1ae)

diff --git a/mi/miexpose.c b/mi/miexpose.c
index 6b6938a75..6239365b5 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -405,6 +405,9 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     BoxPtr pbox;
     xRectangle *prect;
     int numRects, regionnumrects;
+#ifdef COMPOSITE
+    WindowPtr orig_pWin = pWin;
+#endif
 
     /*
      * Distance from screen to destination drawable, use this
@@ -488,6 +491,27 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
         gcval[1].val =
             fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
 #else
+#ifdef COMPOSITE
+        /* Make sure alpha will sample as 1.0 for opaque windows */
+        if (drawable->depth == 32) {
+            int effective_depth = orig_pWin->drawable.depth;
+
+            if (effective_depth == 32) {
+                orig_pWin = orig_pWin->parent;
+                while (orig_pWin && orig_pWin->parent) {
+                    if (orig_pWin->drawable.depth == 24) {
+                        effective_depth = 24;
+                        break;
+                    }
+
+                    orig_pWin = orig_pWin->parent;
+                }
+            }
+
+            if (effective_depth == 24)
+                fill.pixel |= 0xff000000;
+        }
+#endif
         gcval[1].val = fill.pixel;
 #endif
         gcval[2].val = FillSolid;
commit 63fae8a24993127c3d6ca5bb232793c76db84660
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Wed Jul 19 12:26:21 2023 +0200

    glamor: Add and use glamor_drawable_effective_depth helper
    
    Consider the following window hierarchy, from ancestors to descendants:
    
     A
     |
     B
     |
     C
    
    If both A & C have depth 32, but B has depth 24, C must effectively
    behave as if it had depth 24, even if its backing pixmap has depth 32
    as well.
    
    Fixes the xmag issue described in the GitLab issue below.
    
    Issue: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1564
    (cherry picked from commit 3e044b1e64c9eead030031cc98bfc345a5629bcf)

diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c
index 58bfa2b0e..08b55b67b 100644
--- a/glamor/glamor_copy.c
+++ b/glamor/glamor_copy.c
@@ -77,7 +77,7 @@ use_copyplane(DrawablePtr drawable, GCPtr gc, glamor_program *prog, void *arg)
     glamor_set_color(drawable, gc->bgPixel, prog->bg_uniform);
 
     /* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap private knows this? */
-    switch (args->src_drawable->depth) {
+    switch (glamor_drawable_effective_depth(args->src_drawable)) {
     case 30:
         glUniform4ui(prog->bitplane_uniform,
                      (args->bitplane >> 20) & 0x3ff,
@@ -235,7 +235,7 @@ glamor_copy_cpu_fbo(DrawablePtr src,
 
         PixmapPtr tmp_pix = fbCreatePixmap(screen, dst_pixmap->drawable.width,
                                            dst_pixmap->drawable.height,
-                                           dst->depth, 0);
+                                           glamor_drawable_effective_depth(dst), 0);
 
         if (!tmp_pix) {
             glamor_finish_access(src);
@@ -547,7 +547,7 @@ glamor_copy_fbo_fbo_temp(DrawablePtr src,
     tmp_pixmap = glamor_create_pixmap(screen,
                                       bounds.x2 - bounds.x1,
                                       bounds.y2 - bounds.y1,
-                                      src->depth, 0);
+                                      glamor_drawable_effective_depth(src), 0);
     if (!tmp_pixmap)
         goto bail;
 
@@ -757,7 +757,7 @@ glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
                   int srcx, int srcy, int width, int height, int dstx, int dsty,
                   unsigned long bitplane)
 {
-    if ((bitplane & FbFullMask(src->depth)) == 0)
+    if ((bitplane & FbFullMask(glamor_drawable_effective_depth(src))) == 0)
         return miHandleExposures(src, dst, gc,
                                  srcx, srcy, width, height, dstx, dsty);
     return miDoCopy(src, dst, gc,
diff --git a/glamor/glamor_image.c b/glamor/glamor_image.c
index 1a8e527b6..28bdc159f 100644
--- a/glamor/glamor_image.c
+++ b/glamor/glamor_image.c
@@ -129,7 +129,7 @@ glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h,
                           -x, -y,
                           (uint8_t *) d, byte_stride);
 
-    if (!glamor_pm_is_solid(drawable->depth, plane_mask)) {
+    if (!glamor_pm_is_solid(glamor_drawable_effective_depth(drawable), plane_mask)) {
         FbStip pm = fbReplicatePixel(plane_mask, drawable->bitsPerPixel);
         FbStip *dst = (void *)d;
         uint32_t dstStride = byte_stride / sizeof(FbStip);
diff --git a/glamor/glamor_prepare.c b/glamor/glamor_prepare.c
index 2bab2b613..fba875e28 100644
--- a/glamor/glamor_prepare.c
+++ b/glamor/glamor_prepare.c
@@ -163,7 +163,7 @@ glamor_finish_access(DrawablePtr drawable)
         return;
 
     if (priv->pbo &&
-        !(drawable->depth == 24 && pixmap->drawable.depth == 32)) {
+        !(glamor_drawable_effective_depth(drawable) == 24 && pixmap->drawable.depth == 32)) {
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->pbo);
         glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
         pixmap->devPrivate.ptr = NULL;
@@ -179,7 +179,7 @@ glamor_finish_access(DrawablePtr drawable)
     RegionUninit(&priv->prepare_region);
 
     if (priv->pbo) {
-        if (drawable->depth == 24 && pixmap->drawable.depth == 32)
+        if (glamor_drawable_effective_depth(drawable) == 24 && pixmap->drawable.depth == 32)
             pixmap->devPrivate.ptr = NULL;
         else
             glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 1032b880b..2f787015d 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -513,6 +513,30 @@ glamor_pixmap_hcnt(glamor_pixmap_private *priv)
     for (box_index = 0; box_index < glamor_pixmap_hcnt(priv) *         \
              glamor_pixmap_wcnt(priv); box_index++)                    \
 
+static inline int
+glamor_drawable_effective_depth(DrawablePtr drawable)
+{
+    WindowPtr window;
+
+    if (drawable->type != DRAWABLE_WINDOW ||
+        drawable->depth != 32)
+        return drawable->depth;
+
+    window = (WindowPtr)drawable;
+    window = window->parent;
+    while (window && window->parent) {
+        /* A depth 32 window with any depth 24 ancestors (other than the root
+         * window) effectively behaves like depth 24
+         */
+        if (window->drawable.depth == 24)
+            return 24;
+
+        window = window->parent;
+    }
+
+    return 32;
+}
+
 /* GC private structure. Currently holds only any computed dash pixmap */
 
 typedef struct {
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 889fe1b36..ed1222621 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -806,7 +806,7 @@ glamor_render_format_is_supported(PicturePtr picture)
         return TRUE;
 
     glamor_priv = glamor_get_screen_private(picture->pDrawable->pScreen);
-    f = &glamor_priv->formats[picture->pDrawable->depth];
+    f = &glamor_priv->formats[glamor_drawable_effective_depth(picture->pDrawable)];
 
     if (!f->rendering_supported)
         return FALSE;
diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
index a2727f109..9404e899c 100644
--- a/glamor/glamor_transfer.c
+++ b/glamor/glamor_transfer.c
@@ -41,7 +41,7 @@ glamor_upload_boxes(DrawablePtr drawable, BoxPtr in_boxes, int in_nbox,
     const struct glamor_format *f = glamor_format_for_pixmap(pixmap);
     char *tmp_bits = NULL;
 
-    if (drawable->depth == 24 && pixmap->drawable.depth == 32)
+    if (glamor_drawable_effective_depth(drawable) == 24 && pixmap->drawable.depth == 32)
         tmp_bits = xnfalloc(byte_stride * pixmap->drawable.height);
 
     glamor_make_current(glamor_priv);
diff --git a/glamor/glamor_transform.h b/glamor/glamor_transform.h
index 305253310..6eef2fc7a 100644
--- a/glamor/glamor_transform.h
+++ b/glamor/glamor_transform.h
@@ -44,7 +44,8 @@ glamor_set_color(DrawablePtr    drawable,
                  GLint          uniform)
 {
     glamor_set_color_depth(drawable->pScreen,
-                           drawable->depth, pixel, uniform);
+                           glamor_drawable_effective_depth(drawable),
+                           pixel, uniform);
 }
 
 Bool


More information about the xorg-commit mailing list