[metacity] compositor-xrender: move shadow to MetaShadowXRender



commit 16a3262615e7d1cf5de89a6e9cc8d58ad5c6ad2c
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Tue Oct 22 23:45:02 2019 +0300

    compositor-xrender: move shadow to MetaShadowXRender

 src/Makefile.am                          |   2 +
 src/compositor/meta-compositor-xrender.c | 200 +++++++++++++++----------------
 src/compositor/meta-shadow-xrender.c     |  78 ++++++++++++
 src/compositor/meta-shadow-xrender.h     |  54 +++++++++
 4 files changed, 228 insertions(+), 106 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 98f9a698..bc7915eb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,8 @@ metacity_SOURCES=                             \
        compositor/meta-compositor-private.h    \
        compositor/meta-compositor-xrender.c    \
        compositor/meta-compositor-xrender.h    \
+       compositor/meta-shadow-xrender.c        \
+       compositor/meta-shadow-xrender.h        \
        compositor/meta-surface.c               \
        compositor/meta-surface.h               \
        compositor/meta-surface-private.h       \
diff --git a/src/compositor/meta-compositor-xrender.c b/src/compositor/meta-compositor-xrender.c
index 51063ca9..1585fae6 100644
--- a/src/compositor/meta-compositor-xrender.c
+++ b/src/compositor/meta-compositor-xrender.c
@@ -39,6 +39,7 @@
 #include "prefs.h"
 #include "window-private.h"
 #include "meta-compositor-xrender.h"
+#include "meta-shadow-xrender.h"
 #include "meta-surface-xrender.h"
 #include "xprops.h"
 #include "util.h"
@@ -87,13 +88,7 @@ typedef struct _MetaCompWindow
 
   MetaRectangle rect;
 
-  XserverRegion shadow_region;
-
-  Picture shadow;
-  int shadow_dx;
-  int shadow_dy;
-  int shadow_width;
-  int shadow_height;
+  MetaShadowXRender *shadow;
 
   gboolean shadow_changed;
 } MetaCompWindow;
@@ -113,7 +108,6 @@ struct _MetaCompositorXRender
 
   Picture         root_picture;
   Picture         root_buffer;
-  Picture         black_picture;
   Picture         root_tile;
 
   gboolean        prefs_listener_added;
@@ -737,6 +731,7 @@ shadow_changed (MetaSurface *surface)
   MetaCompositor *compositor;
   MetaCompositorXRender *xrender;
   MetaCompWindow *cw;
+  XserverRegion shadow_region;
 
   compositor = meta_surface_get_compositor (surface);
   xrender = META_COMPOSITOR_XRENDER (compositor);
@@ -746,78 +741,89 @@ shadow_changed (MetaSurface *surface)
 
   cw = g_object_get_data (G_OBJECT (surface), "cw");
 
-  if (cw->shadow_region != None)
+  if (cw->shadow == NULL)
     {
-      meta_compositor_add_damage (compositor, "shadow_changed", cw->shadow_region);
-      XFixesDestroyRegion (xrender->xdisplay, cw->shadow_region);
-      cw->shadow_region = None;
+      meta_compositor_queue_redraw (compositor);
+      return;
     }
 
-  if (cw->shadow != None)
-    {
-      XRenderFreePicture (xrender->xdisplay, cw->shadow);
-      cw->shadow = None;
-    }
+  shadow_region = meta_shadow_xrender_get_region (cw->shadow);
+  XFixesTranslateRegion (xrender->xdisplay, shadow_region, cw->rect.x, cw->rect.y);
+  meta_compositor_add_damage (compositor, "shadow_changed", shadow_region);
+  XFixesDestroyRegion (xrender->xdisplay, shadow_region);
 
-  meta_compositor_queue_redraw (compositor);
+  meta_shadow_xrender_free (cw->shadow);
+  cw->shadow = NULL;
 
   cw->shadow_changed = TRUE;
 }
 
-static XserverRegion
-get_shadow_region (MetaCompositorXRender *xrender,
-                   MetaCompWindow        *cw,
-                   MetaShadowType         shadow_type)
+static MetaShadowXRender *
+create_shadow (MetaCompositorXRender *xrender,
+               MetaSurface           *surface,
+               MetaShadowType         shadow_type)
 {
-  MetaFrame *frame;
+  MetaWindow *window;
   MetaFrameBorders borders;
-  XRectangle sr;
-  Display *xdisplay;
-  XserverRegion shadow_region;
+  GtkBorder *invisible;
+  double opacity;
+  int width;
+  int height;
+  MetaShadowXRender *ret;
   cairo_region_t *frame_bounds;
 
-  frame = meta_window_get_frame (cw->window);
-  meta_frame_calc_borders (frame, &borders);
+  window = meta_surface_get_window (surface);
 
-  cw->shadow_dx = (int) shadow_offsets_x [shadow_type] + borders.invisible.left;
-  cw->shadow_dy = (int) shadow_offsets_y [shadow_type] + borders.invisible.top;
+  meta_frame_calc_borders (window->frame, &borders);
+  invisible = &borders.invisible;
 
-  if (!cw->shadow)
-    {
-      double opacity = SHADOW_OPACITY;
-      int invisible_width = borders.invisible.left + borders.invisible.right;
-      int invisible_height = borders.invisible.top + borders.invisible.bottom;
+  opacity = SHADOW_OPACITY;
+  if (window->opacity != OPAQUE)
+    opacity = opacity * ((double) window->opacity) / OPAQUE;
 
-      if (cw->window->opacity != (guint) OPAQUE)
-        opacity = opacity * ((double) cw->window->opacity) / ((double) OPAQUE);
+  width = meta_surface_get_width (surface);
+  height = meta_surface_get_height (surface);
 
-      cw->shadow = shadow_picture (xrender, shadow_type, opacity,
-                                   cw->rect.width - invisible_width,
-                                   cw->rect.height - invisible_height,
-                                   &cw->shadow_width, &cw->shadow_height);
-    }
+  ret = g_new0 (MetaShadowXRender, 1);
+  ret->xdisplay = xrender->xdisplay;
 
-  sr.x = cw->shadow_dx;
-  sr.y = cw->shadow_dy;
-  sr.width = cw->shadow_width;
-  sr.height = cw->shadow_height;
+  ret->dx = shadow_offsets_x[shadow_type] + invisible->left;
+  ret->dy = shadow_offsets_y[shadow_type] + invisible->top;
 
-  xdisplay = xrender->xdisplay;
-  shadow_region = XFixesCreateRegion (xdisplay, &sr, 1);
-  frame_bounds = meta_window_get_frame_bounds (cw->window);
+  ret->black = solid_picture (xrender->xdisplay, TRUE, 1, 0, 0, 0);
+  ret->shadow = shadow_picture (xrender,
+                                shadow_type,
+                                opacity,
+                                width - invisible->left - invisible->right,
+                                height - invisible->top - invisible->bottom,
+                                &ret->width,
+                                &ret->height);
+
+  ret->region = XFixesCreateRegion (xrender->xdisplay, &(XRectangle) {
+                                      .x = ret->dx,
+                                      .y = ret->dy,
+                                      .width = ret->width,
+                                      .height = ret->height
+                                    }, 1);
+
+  frame_bounds = meta_window_get_frame_bounds (window);
 
   if (frame_bounds != NULL)
     {
       XserverRegion bounds_region;
 
-      bounds_region = cairo_region_to_xserver_region (xdisplay, frame_bounds);
-      XFixesSubtractRegion (xdisplay, shadow_region, shadow_region, bounds_region);
-      XFixesDestroyRegion (xdisplay, bounds_region);
-    }
+      bounds_region = cairo_region_to_xserver_region (xrender->xdisplay,
+                                                      frame_bounds);
 
-  XFixesTranslateRegion (xdisplay, shadow_region, cw->rect.x, cw->rect.y);
+      XFixesSubtractRegion (xrender->xdisplay,
+                            ret->region,
+                            ret->region,
+                            bounds_region);
 
-  return shadow_region;
+      XFixesDestroyRegion (xrender->xdisplay, bounds_region);
+    }
+
+  return ret;
 }
 
 static void
@@ -827,21 +833,18 @@ paint_shadow (MetaCompositorXRender *xrender,
               Picture                paint_buffer)
 {
   MetaCompWindow *cw;
-  XserverRegion shadow_clip;
   XserverRegion border_clip;
-  int x;
-  int y;
+  XserverRegion shadow_clip;
 
   cw = g_object_get_data (G_OBJECT (surface_xrender), "cw");
 
-  if (cw->shadow == None)
+  if (cw->shadow == NULL)
     return;
 
-  shadow_clip = XFixesCreateRegion (xrender->xdisplay, NULL, 0);
-  XFixesCopyRegion (xrender->xdisplay, shadow_clip, cw->shadow_region);
-
   border_clip = meta_surface_xrender_get_border_clip (surface_xrender);
-  XFixesIntersectRegion (xrender->xdisplay, shadow_clip, shadow_clip, border_clip);
+
+  shadow_clip = XFixesCreateRegion (xrender->xdisplay, NULL, 0);
+  XFixesCopyRegion (xrender->xdisplay, shadow_clip, border_clip);
 
   if (paint_region != None)
     {
@@ -851,17 +854,13 @@ paint_shadow (MetaCompositorXRender *xrender,
                              paint_region);
     }
 
-  XFixesSetPictureClipRegion (xrender->xdisplay, paint_buffer, 0, 0, shadow_clip);
-  XFixesDestroyRegion (xrender->xdisplay, shadow_clip);
-
-  x = cw->rect.x;
-  y = cw->rect.y;
+  meta_shadow_xrender_paint (cw->shadow,
+                             shadow_clip,
+                             paint_buffer,
+                             cw->rect.x,
+                             cw->rect.y);
 
-  XRenderComposite (xrender->xdisplay, PictOpOver,
-                    xrender->black_picture, cw->shadow, paint_buffer,
-                    0, 0, 0, 0,
-                    x + cw->shadow_dx, y + cw->shadow_dy,
-                    cw->shadow_width, cw->shadow_height);
+  XFixesDestroyRegion (xrender->xdisplay, shadow_clip);
 }
 
 static void
@@ -1027,24 +1026,13 @@ static void
 cw_destroy_cb (gpointer data)
 {
   MetaCompWindow *cw;
-  MetaDisplay *display;
-  Display *xdisplay;
 
   cw = (MetaCompWindow *) data;
 
-  display = meta_window_get_display (cw->window);
-  xdisplay = meta_display_get_xdisplay (display);
-
-  if (cw->shadow)
-    {
-      XRenderFreePicture (xdisplay, cw->shadow);
-      cw->shadow = None;
-    }
-
-  if (cw->shadow_region != None)
+  if (cw->shadow != NULL)
     {
-      XFixesDestroyRegion (xdisplay, cw->shadow_region);
-      cw->shadow_region = None;
+      meta_shadow_xrender_free (cw->shadow);
+      cw->shadow = NULL;
     }
 
   g_free (cw);
@@ -1166,9 +1154,6 @@ meta_compositor_xrender_finalize (GObject *object)
   if (xrender->root_picture)
     XRenderFreePicture (xdisplay, xrender->root_picture);
 
-  if (xrender->black_picture)
-    XRenderFreePicture (xdisplay, xrender->black_picture);
-
   if (xrender->have_shadows)
     {
       int i;
@@ -1246,7 +1231,6 @@ meta_compositor_xrender_manage (MetaCompositor  *compositor,
     }
 
   xrender->root_buffer = None;
-  xrender->black_picture = solid_picture (xdisplay, TRUE, 1, 0, 0, 0);
 
   xrender->root_tile = None;
 
@@ -1404,16 +1388,15 @@ meta_compositor_xrender_sync_window_geometry (MetaCompositor *compositor,
     {
       shadow_changed (surface);
     }
-  else if (cw->shadow_region != None)
+  else if (cw->shadow != NULL)
     {
-      meta_compositor_add_damage (compositor, "sync_window_geometry", cw->shadow_region);
+      XserverRegion region;
 
-      XFixesTranslateRegion (xrender->xdisplay,
-                             cw->shadow_region,
-                             cw->rect.x - old_rect.x,
-                             cw->rect.y - old_rect.y);
+      region = meta_shadow_xrender_get_region (cw->shadow);
+      XFixesTranslateRegion (xrender->xdisplay, region, old_rect.x, old_rect.y);
 
-      meta_compositor_add_damage (compositor, "sync_window_geometry", cw->shadow_region);
+      meta_compositor_add_damage (compositor, "sync_window_geometry", region);
+      XFixesDestroyRegion (xrender->xdisplay, region);
     }
 }
 
@@ -1448,22 +1431,27 @@ meta_compositor_xrender_pre_paint (MetaCompositor *compositor)
           meta_surface_has_shadow (surface))
         {
           MetaShadowType shadow_type;
+          XserverRegion shadow_region;
 
           if (meta_window_appears_focused (cw->window))
             shadow_type = META_SHADOW_LARGE;
           else
             shadow_type = META_SHADOW_MEDIUM;
 
-          g_assert (cw->shadow_region == None);
-          cw->shadow_region = get_shadow_region (xrender, cw, shadow_type);
+          g_assert (cw->shadow == NULL);
+          cw->shadow = create_shadow (xrender, surface, shadow_type);
 
-          if (cw->shadow_region != None)
-            {
-              meta_compositor_add_damage (compositor,
-                                          "meta_compositor_xrender_pre_paint",
-                                          cw->shadow_region);
-            }
+          shadow_region = meta_shadow_xrender_get_region (cw->shadow);
+          XFixesTranslateRegion (xrender->xdisplay,
+                                 shadow_region,
+                                 meta_surface_get_x (surface),
+                                 meta_surface_get_y (surface));
+
+          meta_compositor_add_damage (compositor,
+                                      "meta_compositor_xrender_pre_paint",
+                                      shadow_region);
 
+          XFixesDestroyRegion (xrender->xdisplay, shadow_region);
           cw->shadow_changed = FALSE;
         }
     }
diff --git a/src/compositor/meta-shadow-xrender.c b/src/compositor/meta-shadow-xrender.c
new file mode 100644
index 00000000..058ef057
--- /dev/null
+++ b/src/compositor/meta-shadow-xrender.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "meta-shadow-xrender.h"
+
+void
+meta_shadow_xrender_free (MetaShadowXRender *self)
+{
+  if (self->black != None)
+    {
+      XRenderFreePicture (self->xdisplay, self->black);
+      self->black = None;
+    }
+
+  if (self->shadow != None)
+    {
+      XRenderFreePicture (self->xdisplay, self->shadow);
+      self->shadow = None;
+    }
+
+  if (self->region != None)
+    {
+      XFixesDestroyRegion (self->xdisplay, self->region);
+      self->region = None;
+    }
+
+  g_free (self);
+}
+
+XserverRegion
+meta_shadow_xrender_get_region (MetaShadowXRender *self)
+{
+  XserverRegion region;
+
+  region = XFixesCreateRegion (self->xdisplay, NULL, 0);
+  XFixesCopyRegion (self->xdisplay, region, self->region);
+
+  return region;
+}
+
+void
+meta_shadow_xrender_paint (MetaShadowXRender *self,
+                           XserverRegion      paint_region,
+                           Picture            paint_buffer,
+                           int                x,
+                           int                y)
+{
+  XserverRegion shadow_clip;
+
+  shadow_clip = XFixesCreateRegion (self->xdisplay, NULL, 0);
+  XFixesCopyRegion (self->xdisplay, shadow_clip, self->region);
+  XFixesTranslateRegion (self->xdisplay, shadow_clip, x, y);
+
+  XFixesIntersectRegion (self->xdisplay, shadow_clip, shadow_clip, paint_region);
+  XFixesSetPictureClipRegion (self->xdisplay, paint_buffer, 0, 0, shadow_clip);
+  XFixesDestroyRegion (self->xdisplay, shadow_clip);
+
+  XRenderComposite (self->xdisplay, PictOpOver,
+                    self->black, self->shadow, paint_buffer,
+                    0, 0, 0, 0,
+                    x + self->dx, y + self->dy,
+                    self->width, self->height);
+}
diff --git a/src/compositor/meta-shadow-xrender.h b/src/compositor/meta-shadow-xrender.h
new file mode 100644
index 00000000..d6f2ebf8
--- /dev/null
+++ b/src/compositor/meta-shadow-xrender.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_SHADOW_XRENDER_H
+#define META_SHADOW_XRENDER_H
+
+#include <glib-object.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/Xrender.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+  Display       *xdisplay;
+
+  int            dx;
+  int            dy;
+  int            width;
+  int            height;
+
+  Picture        black;
+  Picture        shadow;
+
+  XserverRegion  region;
+} MetaShadowXRender;
+
+void          meta_shadow_xrender_free       (MetaShadowXRender *self);
+
+XserverRegion meta_shadow_xrender_get_region (MetaShadowXRender *self);
+
+void          meta_shadow_xrender_paint      (MetaShadowXRender *self,
+                                              XserverRegion      paint_region,
+                                              Picture            paint_buffer,
+                                              int                x,
+                                              int                y);
+
+G_END_DECLS
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]