From 2a75661883a4acf6b36694c256a367560269f9a0 Mon Sep 17 00:00:00 2001 From: Bilal Elmoussaoui Date: Mon, 8 Jan 2024 20:55:03 +0100 Subject: [PATCH] region: Move RegionBuilder to Mtk Part-of: --- mtk/mtk/mtk-region.c | 101 ++++++++++++++ mtk/mtk/mtk-region.h | 32 +++++ src/backends/meta-renderer-view.c | 2 +- src/compositor/meta-cullable.c | 1 - src/compositor/meta-shadow-factory.c | 41 +++--- src/compositor/meta-shaped-texture.c | 1 - src/compositor/meta-surface-actor-wayland.c | 1 - src/compositor/meta-surface-actor.c | 1 - src/compositor/meta-window-actor-wayland.c | 1 - src/compositor/meta-window-actor-x11.c | 9 +- src/compositor/meta-window-group.c | 1 - src/compositor/region-utils.c | 127 ------------------ src/compositor/region-utils.h | 53 -------- src/meson.build | 2 - .../meta-pointer-confinement-wayland.c | 1 - src/wayland/meta-wayland-actor-surface.c | 1 - src/wayland/meta-wayland-surface.c | 2 +- 17 files changed, 159 insertions(+), 218 deletions(-) delete mode 100644 src/compositor/region-utils.c delete mode 100644 src/compositor/region-utils.h diff --git a/mtk/mtk/mtk-region.c b/mtk/mtk/mtk-region.c index 98579a4f7..28905dfa7 100644 --- a/mtk/mtk/mtk-region.c +++ b/mtk/mtk/mtk-region.c @@ -515,3 +515,104 @@ mtk_region_iterator_next (MtkRegionIterator *iter) iter->line_end = TRUE; } } + +/* Various algorithms in this file require unioning together a set of rectangles + * that are unsorted or overlap; unioning such a set of rectangles 1-by-1 + * using mtk_region_union_rectangle() produces O(N^2) behavior (if the union + * adds or removes rectangles in the middle of the region, then it has to + * move all the rectangles after that.) To avoid this behavior, MtkRegionBuilder + * creates regions for small groups of rectangles and merges them together in + * a binary tree. + * + * Possible improvement: From a glance at the code, accumulating all the rectangles + * into a flat array and then calling the (not usefully documented) + * mtk_region_create_rectangles() would have the same behavior and would be + * simpler and a bit more efficient. + */ + +/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower. + * But using 8 may be more robust to systems with slow malloc(). */ +#define MAX_CHUNK_RECTANGLES 8 + +void +mtk_region_builder_init (MtkRegionBuilder *builder) +{ + int i; + + for (i = 0; i < MTK_REGION_BUILDER_MAX_LEVELS; i++) + builder->levels[i] = NULL; + builder->n_levels = 1; +} + +void +mtk_region_builder_add_rectangle (MtkRegionBuilder *builder, + int x, + int y, + int width, + int height) +{ + MtkRectangle rect; + int i; + + if (builder->levels[0] == NULL) + builder->levels[0] = mtk_region_create (); + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + + mtk_region_union_rectangle (builder->levels[0], &rect); + if (mtk_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES) + { + for (i = 1; i < builder->n_levels + 1; i++) + { + if (builder->levels[i] == NULL) + { + if (i < MTK_REGION_BUILDER_MAX_LEVELS) + { + builder->levels[i] = builder->levels[i - 1]; + builder->levels[i - 1] = NULL; + if (i == builder->n_levels) + builder->n_levels++; + } + + break; + } + else + { + mtk_region_union (builder->levels[i], builder->levels[i - 1]); + mtk_region_unref (builder->levels[i - 1]); + builder->levels[i - 1] = NULL; + } + } + } +} + +MtkRegion * +mtk_region_builder_finish (MtkRegionBuilder *builder) +{ + MtkRegion *result = NULL; + int i; + + for (i = 0; i < builder->n_levels; i++) + { + if (builder->levels[i]) + { + if (result == NULL) + { + result = builder->levels[i]; + } + else + { + mtk_region_union (result, builder->levels[i]); + mtk_region_unref (builder->levels[i]); + } + } + } + + if (result == NULL) + result = mtk_region_create (); + + return result; +} diff --git a/mtk/mtk/mtk-region.h b/mtk/mtk/mtk-region.h index 7a4e0154e..95da0c458 100644 --- a/mtk/mtk/mtk-region.h +++ b/mtk/mtk/mtk-region.h @@ -176,3 +176,35 @@ gboolean mtk_region_iterator_at_end (MtkRegionIterator *iter); MTK_EXPORT void mtk_region_iterator_next (MtkRegionIterator *iter); + +typedef struct _MtkRegionBuilder MtkRegionBuilder; + +#define MTK_REGION_BUILDER_MAX_LEVELS 16 + +struct _MtkRegionBuilder { + /* To merge regions in binary tree order, we need to keep track of + * the regions that we've already merged together at different + * levels of the tree. We fill in an array in the pattern: + * + * |a | + * |b |a | + * |c | |ab | + * |d |c |ab | + * |e | | |abcd| + */ + MtkRegion *levels[MTK_REGION_BUILDER_MAX_LEVELS]; + int n_levels; +}; + +MTK_EXPORT +void mtk_region_builder_init (MtkRegionBuilder *builder); + +MTK_EXPORT +void mtk_region_builder_add_rectangle (MtkRegionBuilder *builder, + int x, + int y, + int width, + int height); + +MTK_EXPORT +MtkRegion * mtk_region_builder_finish (MtkRegionBuilder *builder); diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c index 6fc82f0f4..f66efa826 100644 --- a/src/backends/meta-renderer-view.c +++ b/src/backends/meta-renderer-view.c @@ -35,7 +35,7 @@ #include "backends/meta-crtc.h" #include "backends/meta-renderer.h" #include "clutter/clutter-mutter.h" -#include "compositor/region-utils.h" +#include "core/boxes-private.h" enum { diff --git a/src/compositor/meta-cullable.c b/src/compositor/meta-cullable.c index 7b6cd2b68..6e55809ec 100644 --- a/src/compositor/meta-cullable.c +++ b/src/compositor/meta-cullable.c @@ -26,7 +26,6 @@ #include "clutter/clutter-mutter.h" #include "compositor/clutter-utils.h" #include "compositor/meta-cullable.h" -#include "compositor/region-utils.h" G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR); diff --git a/src/compositor/meta-shadow-factory.c b/src/compositor/meta-shadow-factory.c index 1483c3991..1817ac81b 100644 --- a/src/compositor/meta-shadow-factory.c +++ b/src/compositor/meta-shadow-factory.c @@ -22,7 +22,6 @@ #include #include "compositor/cogl-utils.h" -#include "compositor/region-utils.h" #include "meta/meta-shadow-factory.h" #include "meta/util.h" @@ -700,23 +699,23 @@ flip_buffer (guchar *buffer, } static void -add_expanded_rect (MetaRegionBuilder *builder, - int x, - int y, - int width, - int height, - int x_amount, - int y_amount, - gboolean flip) +add_expanded_rect (MtkRegionBuilder *builder, + int x, + int y, + int width, + int height, + int x_amount, + int y_amount, + gboolean flip) { if (flip) - meta_region_builder_add_rectangle (builder, - y - y_amount, x - x_amount, - height + 2 * y_amount, width + 2 * x_amount); + mtk_region_builder_add_rectangle (builder, + y - y_amount, x - x_amount, + height + 2 * y_amount, width + 2 * x_amount); else - meta_region_builder_add_rectangle (builder, - x - x_amount, y - y_amount, - width + 2 * x_amount, height + 2 * y_amount); + mtk_region_builder_add_rectangle (builder, + x - x_amount, y - y_amount, + width + 2 * x_amount, height + 2 * y_amount); } static MtkRegion * @@ -725,11 +724,11 @@ expand_region (MtkRegion *region, int y_amount, gboolean flip) { - MetaRegionBuilder builder; + MtkRegionBuilder builder; int n; int i; - meta_region_builder_init (&builder); + mtk_region_builder_init (&builder); n = mtk_region_num_rectangles (region); for (i = 0; i < n; i++) @@ -742,7 +741,7 @@ expand_region (MtkRegion *region, x_amount, y_amount, flip); } - return meta_region_builder_finish (&builder); + return mtk_region_builder_finish (&builder); } /* This computes a (clipped version) of the inverse of the region @@ -753,12 +752,12 @@ expand_region_inverse (MtkRegion *region, int y_amount, gboolean flip) { - MetaRegionBuilder builder; + MtkRegionBuilder builder; MtkRegionIterator iter; MtkRectangle extents; int last_x; - meta_region_builder_init (&builder); + mtk_region_builder_init (&builder); extents = mtk_region_get_extents (region); add_expanded_rect (&builder, @@ -800,7 +799,7 @@ expand_region_inverse (MtkRegion *region, } } - return meta_region_builder_finish (&builder); + return mtk_region_builder_finish (&builder); } /** diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 31417305e..5924dd22d 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -44,7 +44,6 @@ #include "cogl/cogl.h" #include "compositor/clutter-utils.h" #include "compositor/meta-texture-mipmap.h" -#include "compositor/region-utils.h" #include "core/boxes-private.h" #include "meta/meta-shaped-texture.h" diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c index 333ed23da..819672c4a 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c @@ -31,7 +31,6 @@ #include "backends/meta-screen-cast-window.h" #include "compositor/meta-shaped-texture-private.h" #include "compositor/meta-window-actor-private.h" -#include "compositor/region-utils.h" #include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-subsurface.h" diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 1c10b850f..ed90cbbe2 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -24,7 +24,6 @@ #include "compositor/meta-cullable.h" #include "compositor/meta-shaped-texture-private.h" #include "compositor/meta-window-actor-private.h" -#include "compositor/region-utils.h" #include "meta/meta-shaped-texture.h" enum diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c index 4c0517291..805578f0a 100644 --- a/src/compositor/meta-window-actor-wayland.c +++ b/src/compositor/meta-window-actor-wayland.c @@ -24,7 +24,6 @@ #include "compositor/meta-cullable.h" #include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-window-actor-wayland.h" -#include "compositor/region-utils.h" #include "meta/meta-window-actor.h" #include "wayland/meta-wayland-surface-private.h" #include "wayland/meta-window-wayland.h" diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c index 8574df604..e8b363fcf 100644 --- a/src/compositor/meta-window-actor-x11.c +++ b/src/compositor/meta-window-actor-x11.c @@ -29,7 +29,6 @@ #include "compositor/meta-shaped-texture-private.h" #include "compositor/meta-surface-actor.h" #include "compositor/meta-surface-actor-x11.h" -#include "compositor/region-utils.h" #include "core/frame.h" #include "core/window-private.h" #include "meta/compositor.h" @@ -705,9 +704,9 @@ scan_visible_region (guchar *mask_data, MtkRegion *scan_area) { int i, n_rects = mtk_region_num_rectangles (scan_area); - MetaRegionBuilder builder; + MtkRegionBuilder builder; - meta_region_builder_init (&builder); + mtk_region_builder_init (&builder); for (i = 0; i < n_rects; i++) { @@ -726,14 +725,14 @@ scan_visible_region (guchar *mask_data, if (x2 > x) { - meta_region_builder_add_rectangle (&builder, x, y, x2 - x, 1); + mtk_region_builder_add_rectangle (&builder, x, y, x2 - x, 1); x = x2; } } } } - return meta_region_builder_finish (&builder); + return mtk_region_builder_finish (&builder); } static void diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c index b88648f54..0b29409f5 100644 --- a/src/compositor/meta-window-group.c +++ b/src/compositor/meta-window-group.c @@ -9,7 +9,6 @@ #include "compositor/meta-cullable.h" #include "compositor/meta-window-actor-private.h" #include "compositor/meta-window-group-private.h" -#include "compositor/region-utils.h" #include "core/display-private.h" #include "core/window-private.h" diff --git a/src/compositor/region-utils.c b/src/compositor/region-utils.c deleted file mode 100644 index 0a42ed95e..000000000 --- a/src/compositor/region-utils.c +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for region manipulation - * - * Copyright (C) 2010 Red Hat, Inc. - * - * 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 . - */ - -#include "config.h" - -#include "backends/meta-monitor-transform.h" -#include "compositor/region-utils.h" -#include "core/boxes-private.h" - -#include - -/* MetaRegionBuilder */ - -/* Various algorithms in this file require unioning together a set of rectangles - * that are unsorted or overlap; unioning such a set of rectangles 1-by-1 - * using mtk_region_union_rectangle() produces O(N^2) behavior (if the union - * adds or removes rectangles in the middle of the region, then it has to - * move all the rectangles after that.) To avoid this behavior, MetaRegionBuilder - * creates regions for small groups of rectangles and merges them together in - * a binary tree. - * - * Possible improvement: From a glance at the code, accumulating all the rectangles - * into a flat array and then calling the (not usefully documented) - * mtk_region_create_rectangles() would have the same behavior and would be - * simpler and a bit more efficient. - */ - -/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower. - * But using 8 may be more robust to systems with slow malloc(). */ -#define MAX_CHUNK_RECTANGLES 8 - -void -meta_region_builder_init (MetaRegionBuilder *builder) -{ - int i; - for (i = 0; i < META_REGION_BUILDER_MAX_LEVELS; i++) - builder->levels[i] = NULL; - builder->n_levels = 1; -} - -void -meta_region_builder_add_rectangle (MetaRegionBuilder *builder, - int x, - int y, - int width, - int height) -{ - MtkRectangle rect; - int i; - - if (builder->levels[0] == NULL) - builder->levels[0] = mtk_region_create (); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - - mtk_region_union_rectangle (builder->levels[0], &rect); - if (mtk_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES) - { - for (i = 1; i < builder->n_levels + 1; i++) - { - if (builder->levels[i] == NULL) - { - if (i < META_REGION_BUILDER_MAX_LEVELS) - { - builder->levels[i] = builder->levels[i - 1]; - builder->levels[i - 1] = NULL; - if (i == builder->n_levels) - builder->n_levels++; - } - - break; - } - else - { - mtk_region_union (builder->levels[i], builder->levels[i - 1]); - mtk_region_unref (builder->levels[i - 1]); - builder->levels[i - 1] = NULL; - } - } - } -} - -MtkRegion * -meta_region_builder_finish (MetaRegionBuilder *builder) -{ - MtkRegion *result = NULL; - int i; - - for (i = 0; i < builder->n_levels; i++) - { - if (builder->levels[i]) - { - if (result == NULL) - result = builder->levels[i]; - else - { - mtk_region_union (result, builder->levels[i]); - mtk_region_unref (builder->levels[i]); - } - } - } - - if (result == NULL) - result = mtk_region_create (); - - return result; -} diff --git a/src/compositor/region-utils.h b/src/compositor/region-utils.h deleted file mode 100644 index e8a335611..000000000 --- a/src/compositor/region-utils.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for region manipulation - * - * Copyright (C) 2010 Red Hat, Inc. - * - * 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 . - */ - -#pragma once - -#include - -#include "backends/meta-backend-types.h" -#include "clutter/clutter.h" -#include "core/boxes-private.h" - -typedef struct _MetaRegionBuilder MetaRegionBuilder; - -#define META_REGION_BUILDER_MAX_LEVELS 16 -struct _MetaRegionBuilder { - /* To merge regions in binary tree order, we need to keep track of - * the regions that we've already merged together at different - * levels of the tree. We fill in an array in the pattern: - * - * |a | - * |b |a | - * |c | |ab | - * |d |c |ab | - * |e | | |abcd| - */ - MtkRegion *levels[META_REGION_BUILDER_MAX_LEVELS]; - int n_levels; -}; - -void meta_region_builder_init (MetaRegionBuilder *builder); -void meta_region_builder_add_rectangle (MetaRegionBuilder *builder, - int x, - int y, - int width, - int height); -MtkRegion * meta_region_builder_finish (MetaRegionBuilder *builder); diff --git a/src/meson.build b/src/meson.build index 3b7f2015a..945d38a40 100644 --- a/src/meson.build +++ b/src/meson.build @@ -334,8 +334,6 @@ mutter_sources = [ 'compositor/meta-window-group.c', 'compositor/meta-window-group-private.h', 'compositor/meta-window-shape.c', - 'compositor/region-utils.c', - 'compositor/region-utils.h', 'core/bell.c', 'core/bell.h', 'core/boxes.c', diff --git a/src/wayland/meta-pointer-confinement-wayland.c b/src/wayland/meta-pointer-confinement-wayland.c index bbc9bf4e2..148829be3 100644 --- a/src/wayland/meta-pointer-confinement-wayland.c +++ b/src/wayland/meta-pointer-confinement-wayland.c @@ -38,7 +38,6 @@ #include "backends/meta-backend-private.h" #include "backends/meta-pointer-constraint.h" -#include "compositor/region-utils.h" #include "wayland/meta-wayland-pointer-constraints.h" #include "wayland/meta-wayland-pointer.h" #include "wayland/meta-wayland-seat.h" diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index c884e7841..6b3804df5 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -25,7 +25,6 @@ #include "backends/meta-logical-monitor.h" #include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-window-actor-wayland.h" -#include "compositor/region-utils.h" #include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-surface-private.h" #include "wayland/meta-window-wayland.h" diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 0c44cc3aa..d31791bb9 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -31,7 +31,7 @@ #include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor.h" #include "compositor/meta-window-actor-private.h" -#include "compositor/region-utils.h" +#include "core/boxes-private.h" #include "core/display-private.h" #include "core/window-private.h" #include "wayland/meta-wayland-actor-surface.h"