[metacity] compositor-xrender: move window painting to MetaSurfaceXRender
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity] compositor-xrender: move window painting to MetaSurfaceXRender
- Date: Fri, 18 Oct 2019 16:43:28 +0000 (UTC)
commit 097357c62c94c04ccb1da439eb4d3a542e693aef
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Fri Oct 18 15:41:58 2019 +0300
compositor-xrender: move window painting to MetaSurfaceXRender
src/compositor/meta-compositor-xrender.c | 118 +++--------------
src/compositor/meta-surface-xrender.c | 218 +++++++++++++++++++++++++++++--
src/compositor/meta-surface-xrender.h | 9 +-
3 files changed, 233 insertions(+), 112 deletions(-)
---
diff --git a/src/compositor/meta-compositor-xrender.c b/src/compositor/meta-compositor-xrender.c
index ea081de2..72b73d80 100644
--- a/src/compositor/meta-compositor-xrender.c
+++ b/src/compositor/meta-compositor-xrender.c
@@ -109,8 +109,6 @@ typedef struct _MetaCompWindow
int shadow_width;
int shadow_height;
- XserverRegion border_clip;
-
/* This is a copy of the original unshaded window so that we can still see
* what the window looked like when it is needed for the _get_window_surface
* function.
@@ -1175,19 +1173,23 @@ paint_dock_shadows (MetaCompositorXRender *xrender,
for (l = surfaces; l != NULL; l = l->next)
{
- MetaSurface *surface;
+ MetaSurfaceXRender *surface;
MetaCompWindow *cw;
XserverRegion shadow_clip;
- surface = META_SURFACE (l->data);
+ surface = META_SURFACE_XRENDER (l->data);
cw = g_object_get_data (G_OBJECT (surface), "cw");
if (cw->window->type == META_WINDOW_DOCK &&
cw->needs_shadow && cw->shadow)
{
+ XserverRegion border_clip;
+
shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0);
+ border_clip = meta_surface_xrender_get_border_clip (surface);
+
XFixesIntersectRegion (xdisplay, shadow_clip,
- cw->border_clip, region);
+ border_clip, region);
XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, shadow_clip);
@@ -1241,13 +1243,12 @@ paint_windows (MetaCompositorXRender *xrender,
last = NULL;
for (index = surfaces; index; index = index->next)
{
- MetaSurface *surface;
- Picture picture;
+ MetaSurfaceXRender *surface;
/* Store the last window we dealt with */
last = index;
- surface = META_SURFACE (index->data);
+ surface = META_SURFACE_XRENDER (index->data);
cw = g_object_get_data (G_OBJECT (surface), "cw");
if (!cw->damaged)
@@ -1256,11 +1257,9 @@ paint_windows (MetaCompositorXRender *xrender,
continue;
}
- if (!meta_surface_is_visible (surface))
+ if (!meta_surface_is_visible (META_SURFACE (surface)))
continue;
- picture = meta_surface_xrender_get_picture (META_SURFACE_XRENDER (surface));
-
if (cw->window_region == None)
cw->window_region = get_window_region (display, cw);
@@ -1273,50 +1272,15 @@ paint_windows (MetaCompositorXRender *xrender,
if (cw->extents == None)
cw->extents = win_extents (xrender, cw);
+ meta_surface_xrender_paint (surface, paint_region, root_buffer, TRUE);
+
if (cw->mode == WINDOW_SOLID)
{
- int x, y, wid, hei;
- MetaFrame *frame;
- MetaFrameBorders borders;
-
- x = cw->rect.x;
- y = cw->rect.y;
- wid = cw->rect.width;
- hei = cw->rect.height;
-
- frame = meta_window_get_frame (cw->window);
- meta_frame_calc_borders (frame, &borders);
-
- XFixesSetPictureClipRegion (xdisplay, root_buffer,
- 0, 0, paint_region);
- XRenderComposite (xdisplay, PictOpSrc, picture, None, root_buffer,
- borders.total.left, borders.total.top, 0, 0,
- x + borders.total.left, y + borders.total.top,
- wid - borders.total.left - borders.total.right,
- hei - borders.total.top - borders.total.bottom);
-
if (cw->window->type == META_WINDOW_DESKTOP)
{
desktop_region = XFixesCreateRegion (xdisplay, 0, 0);
XFixesCopyRegion (xdisplay, desktop_region, paint_region);
}
-
- if (frame == NULL)
- {
- XFixesSubtractRegion (xdisplay, paint_region,
- paint_region, cw->window_region);
- }
- else
- {
- XFixesSubtractRegion (xdisplay, paint_region,
- paint_region, cw->client_region);
- }
- }
-
- if (!cw->border_clip)
- {
- cw->border_clip = XFixesCreateRegion (xdisplay, 0, 0);
- XFixesCopyRegion (xdisplay, cw->border_clip, paint_region);
}
}
@@ -1334,31 +1298,27 @@ paint_windows (MetaCompositorXRender *xrender,
*/
for (index = last; index; index = index->prev)
{
- MetaSurface *surface;
- Picture picture;
- Picture mask;
+ MetaSurfaceXRender *surface;
- surface = META_SURFACE (index->data);
+ surface = META_SURFACE_XRENDER (index->data);
cw = g_object_get_data (G_OBJECT (surface), "cw");
- picture = meta_surface_xrender_get_picture (META_SURFACE_XRENDER (surface));
- mask = meta_surface_xrender_get_mask_picture (META_SURFACE_XRENDER (surface));
-
- if (picture)
+ if (meta_surface_xrender_get_picture (surface) != None)
{
- int x, y, wid, hei;
+ int x, y;
x = cw->rect.x;
y = cw->rect.y;
- wid = cw->rect.width;
- hei = cw->rect.height;
if (cw->shadow && cw->window->type != META_WINDOW_DOCK)
{
XserverRegion shadow_clip;
+ XserverRegion border_clip;
shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0);
- XFixesSubtractRegion (xdisplay, shadow_clip, cw->border_clip,
+ border_clip = meta_surface_xrender_get_border_clip (surface);
+
+ XFixesSubtractRegion (xdisplay, shadow_clip, border_clip,
cw->visible_region);
XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0,
shadow_clip);
@@ -1372,29 +1332,7 @@ paint_windows (MetaCompositorXRender *xrender,
XFixesDestroyRegion (xdisplay, shadow_clip);
}
- XFixesIntersectRegion (xdisplay, cw->border_clip, cw->border_clip,
- cw->window_region);
- XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0,
- cw->border_clip);
-
- if (cw->mode == WINDOW_SOLID && mask != None)
- {
- XRenderComposite (xdisplay, PictOpOver, picture,
- mask, root_buffer, 0, 0, 0, 0,
- x, y, wid, hei);
- }
- else if (cw->mode == WINDOW_ARGB)
- {
- XRenderComposite (xdisplay, PictOpOver, picture,
- mask, root_buffer, 0, 0, 0, 0,
- x, y, wid, hei);
- }
- }
-
- if (cw->border_clip)
- {
- XFixesDestroyRegion (xdisplay, cw->border_clip);
- cw->border_clip = None;
+ meta_surface_xrender_paint (surface, paint_region, root_buffer, FALSE);
}
}
@@ -1504,12 +1442,6 @@ free_win (MetaCompWindow *cw,
cw->client_region = None;
}
- if (cw->border_clip)
- {
- XFixesDestroyRegion (xdisplay, cw->border_clip);
- cw->border_clip = None;
- }
-
if (cw->extents)
{
XFixesDestroyRegion (xdisplay, cw->extents);
@@ -1650,12 +1582,6 @@ notify_decorated_cb (MetaWindow *window,
cw->shadow = None;
}
- if (cw->border_clip != None)
- {
- XFixesDestroyRegion (xrender->xdisplay, cw->border_clip);
- cw->border_clip = None;
- }
-
determine_mode (xrender, cw);
cw->needs_shadow = window_has_shadow (xrender, cw);
@@ -2022,8 +1948,6 @@ meta_compositor_xrender_add_window (MetaCompositor *compositor,
else
cw->shadow_type = META_SHADOW_MEDIUM;
- cw->border_clip = None;
-
cw->shaded_surface = NULL;
determine_mode (xrender, cw);
diff --git a/src/compositor/meta-surface-xrender.c b/src/compositor/meta-surface-xrender.c
index 35c9239a..d119281a 100644
--- a/src/compositor/meta-surface-xrender.c
+++ b/src/compositor/meta-surface-xrender.c
@@ -31,19 +31,182 @@
struct _MetaSurfaceXRender
{
- MetaSurface parent;
+ MetaSurface parent;
- MetaDisplay *display;
- Display *xdisplay;
+ MetaDisplay *display;
+ Display *xdisplay;
- Picture picture;
+ Picture picture;
- Pixmap mask_pixmap;
- Picture mask_picture;
+ Pixmap mask_pixmap;
+ Picture mask_picture;
+
+ XserverRegion border_clip;
};
G_DEFINE_TYPE (MetaSurfaceXRender, meta_surface_xrender, META_TYPE_SURFACE)
+static gboolean
+is_argb (MetaSurfaceXRender *self)
+{
+ MetaWindow *window;
+ Visual *xvisual;
+ XRenderPictFormat *format;
+
+ window = meta_surface_get_window (META_SURFACE (self));
+ xvisual = meta_window_get_toplevel_xvisual (window);
+
+ format = XRenderFindVisualFormat (self->xdisplay, xvisual);
+
+ if (format && format->type == PictTypeDirect && format->direct.alphaMask)
+ return TRUE;
+
+ if (window->opacity != OPAQUE)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+is_region_empty (Display *xdisplay,
+ XserverRegion region)
+{
+ int n_rects;
+ XRectangle bounds;
+ XRectangle *rects;
+
+ rects = XFixesFetchRegionAndBounds (xdisplay, region, &n_rects, &bounds);
+
+ if (rects != NULL)
+ XFree (rects);
+
+ if (n_rects == 0 || bounds.width == 0 || bounds.height == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+paint_opaque_parts (MetaSurfaceXRender *self,
+ XserverRegion paint_region,
+ Picture paint_buffer)
+{
+ MetaSurface *surface;
+ MetaWindow *window;
+ XserverRegion shape_region;
+ XserverRegion opaque_region;
+ int x;
+ int y;
+ int width;
+ int height;
+ XserverRegion clip_region;
+
+ surface = META_SURFACE (self);
+
+ window = meta_surface_get_window (surface);
+ shape_region = meta_surface_get_shape_region (surface);
+ opaque_region = meta_surface_get_opaque_region (surface);
+
+ if ((is_argb (self) && opaque_region == None) ||
+ window->opacity != OPAQUE)
+ return;
+
+ x = meta_surface_get_x (surface);
+ y = meta_surface_get_y (surface);
+ width = meta_surface_get_width (surface);
+ height = meta_surface_get_height (surface);
+
+ clip_region = XFixesCreateRegion (self->xdisplay, NULL, 0);
+ XFixesCopyRegion (self->xdisplay, clip_region, shape_region);
+
+ if (window->frame != NULL)
+ {
+ MetaFrameBorders borders;
+ XRectangle client_rect;
+ XserverRegion client_region;
+
+ meta_frame_calc_borders (window->frame, &borders);
+
+ client_rect = (XRectangle) {
+ .x = borders.total.left,
+ .y = borders.total.top,
+ .width = width - borders.total.left - borders.total.right,
+ .height = height - borders.total.top - borders.total.bottom
+ };
+
+ client_region = XFixesCreateRegion (self->xdisplay, &client_rect, 1);
+
+ XFixesIntersectRegion (self->xdisplay, clip_region, clip_region, client_region);
+ XFixesDestroyRegion (self->xdisplay, client_region);
+ }
+
+ if (opaque_region != None)
+ XFixesIntersectRegion (self->xdisplay, clip_region, clip_region, opaque_region);
+
+ XFixesTranslateRegion (self->xdisplay, clip_region, x, y);
+ XFixesIntersectRegion (self->xdisplay, clip_region, clip_region, paint_region);
+
+ if (is_region_empty (self->xdisplay, clip_region))
+ {
+ XFixesDestroyRegion (self->xdisplay, clip_region);
+ return;
+ }
+
+ XFixesSetPictureClipRegion (self->xdisplay, paint_buffer, 0, 0, clip_region);
+
+ XRenderComposite (self->xdisplay, PictOpSrc,
+ self->picture, None, paint_buffer,
+ 0, 0, 0, 0,
+ x, y, width, height);
+
+ XFixesSubtractRegion (self->xdisplay, paint_region, paint_region, clip_region);
+ XFixesDestroyRegion (self->xdisplay, clip_region);
+}
+
+static void
+paint_argb_parts (MetaSurfaceXRender *self,
+ Picture paint_buffer)
+{
+ MetaSurface *surface;
+ int x;
+ int y;
+ int width;
+ int height;
+ XserverRegion border_clip;
+ XserverRegion shape_region;
+ XserverRegion clip_region;
+
+ if (is_region_empty (self->xdisplay, self->border_clip))
+ return;
+
+ surface = META_SURFACE (self);
+
+ x = meta_surface_get_x (surface);
+ y = meta_surface_get_y (surface);
+ width = meta_surface_get_width (surface);
+ height = meta_surface_get_height (surface);
+
+ border_clip = self->border_clip;
+ shape_region = meta_surface_get_shape_region (surface);
+
+ clip_region = XFixesCreateRegion (self->xdisplay, NULL, 0);
+ XFixesCopyRegion (self->xdisplay, clip_region, shape_region);
+
+ XFixesTranslateRegion (self->xdisplay, clip_region, x, y);
+ XFixesIntersectRegion (self->xdisplay, border_clip, border_clip, clip_region);
+ XFixesDestroyRegion (self->xdisplay, clip_region);
+
+ if (is_region_empty (self->xdisplay, border_clip))
+ return;
+
+ XFixesSetPictureClipRegion (self->xdisplay, paint_buffer, 0, 0, border_clip);
+
+ XRenderComposite (self->xdisplay, PictOpOver,
+ self->picture, self->mask_picture, paint_buffer,
+ 0, 0, 0, 0,
+ x, y, width, height);
+}
+
static void
clip_to_shape_region (MetaSurfaceXRender *self,
cairo_t *cr)
@@ -317,6 +480,12 @@ meta_surface_xrender_finalize (GObject *object)
free_mask_pixmap (self);
free_mask_picture (self);
+ if (self->border_clip != None)
+ {
+ XFixesDestroyRegion (self->xdisplay, self->border_clip);
+ self->border_clip = None;
+ }
+
G_OBJECT_CLASS (meta_surface_xrender_parent_class)->finalize (object);
}
@@ -523,14 +692,39 @@ meta_surface_xrender_get_picture (MetaSurfaceXRender *self)
return self->picture;
}
-Pixmap
-meta_surface_xrender_get_mask_pixmap (MetaSurfaceXRender *self)
+XserverRegion
+meta_surface_xrender_get_border_clip (MetaSurfaceXRender *self)
{
- return self->mask_pixmap;
+ return self->border_clip;
}
-Picture
-meta_surface_xrender_get_mask_picture (MetaSurfaceXRender *self)
+void
+meta_surface_xrender_paint (MetaSurfaceXRender *self,
+ XserverRegion paint_region,
+ Picture paint_buffer,
+ gboolean opaque)
{
- return self->mask_picture;
+ if (!meta_surface_is_visible (META_SURFACE (self)) ||
+ self->picture == None)
+ return;
+
+ if (opaque)
+ {
+ paint_opaque_parts (self, paint_region, paint_buffer);
+
+ g_assert (self->border_clip == None);
+
+ self->border_clip = XFixesCreateRegion (self->xdisplay, NULL, 0);
+ XFixesCopyRegion (self->xdisplay, self->border_clip, paint_region);
+ }
+ else
+ {
+ paint_argb_parts (self, paint_buffer);
+
+ if (self->border_clip != None)
+ {
+ XFixesDestroyRegion (self->xdisplay, self->border_clip);
+ self->border_clip = None;
+ }
+ }
}
diff --git a/src/compositor/meta-surface-xrender.h b/src/compositor/meta-surface-xrender.h
index a402749e..9729be1c 100644
--- a/src/compositor/meta-surface-xrender.h
+++ b/src/compositor/meta-surface-xrender.h
@@ -27,11 +27,14 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (MetaSurfaceXRender, meta_surface_xrender,
META, SURFACE_XRENDER, MetaSurface)
-Picture meta_surface_xrender_get_picture (MetaSurfaceXRender *self);
+Picture meta_surface_xrender_get_picture (MetaSurfaceXRender *self);
-Pixmap meta_surface_xrender_get_mask_pixmap (MetaSurfaceXRender *self);
+XserverRegion meta_surface_xrender_get_border_clip (MetaSurfaceXRender *self);
-Picture meta_surface_xrender_get_mask_picture (MetaSurfaceXRender *self);
+void meta_surface_xrender_paint (MetaSurfaceXRender *self,
+ XserverRegion paint_region,
+ Picture paint_buffer,
+ gboolean opaque);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]