1
0
Fork 0

region: Move RegionBuilder to Mtk

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3501>
This commit is contained in:
Bilal Elmoussaoui 2024-01-08 20:55:03 +01:00 committed by Marge Bot
parent fced59b33d
commit 2a75661883
17 changed files with 159 additions and 218 deletions

View file

@ -515,3 +515,104 @@ mtk_region_iterator_next (MtkRegionIterator *iter)
iter->line_end = TRUE; 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;
}

View file

@ -176,3 +176,35 @@ gboolean mtk_region_iterator_at_end (MtkRegionIterator *iter);
MTK_EXPORT MTK_EXPORT
void mtk_region_iterator_next (MtkRegionIterator *iter); 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);

View file

@ -35,7 +35,7 @@
#include "backends/meta-crtc.h" #include "backends/meta-crtc.h"
#include "backends/meta-renderer.h" #include "backends/meta-renderer.h"
#include "clutter/clutter-mutter.h" #include "clutter/clutter-mutter.h"
#include "compositor/region-utils.h" #include "core/boxes-private.h"
enum enum
{ {

View file

@ -26,7 +26,6 @@
#include "clutter/clutter-mutter.h" #include "clutter/clutter-mutter.h"
#include "compositor/clutter-utils.h" #include "compositor/clutter-utils.h"
#include "compositor/meta-cullable.h" #include "compositor/meta-cullable.h"
#include "compositor/region-utils.h"
G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR); G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR);

View file

@ -22,7 +22,6 @@
#include <string.h> #include <string.h>
#include "compositor/cogl-utils.h" #include "compositor/cogl-utils.h"
#include "compositor/region-utils.h"
#include "meta/meta-shadow-factory.h" #include "meta/meta-shadow-factory.h"
#include "meta/util.h" #include "meta/util.h"
@ -700,7 +699,7 @@ flip_buffer (guchar *buffer,
} }
static void static void
add_expanded_rect (MetaRegionBuilder *builder, add_expanded_rect (MtkRegionBuilder *builder,
int x, int x,
int y, int y,
int width, int width,
@ -710,11 +709,11 @@ add_expanded_rect (MetaRegionBuilder *builder,
gboolean flip) gboolean flip)
{ {
if (flip) if (flip)
meta_region_builder_add_rectangle (builder, mtk_region_builder_add_rectangle (builder,
y - y_amount, x - x_amount, y - y_amount, x - x_amount,
height + 2 * y_amount, width + 2 * x_amount); height + 2 * y_amount, width + 2 * x_amount);
else else
meta_region_builder_add_rectangle (builder, mtk_region_builder_add_rectangle (builder,
x - x_amount, y - y_amount, x - x_amount, y - y_amount,
width + 2 * x_amount, height + 2 * y_amount); width + 2 * x_amount, height + 2 * y_amount);
} }
@ -725,11 +724,11 @@ expand_region (MtkRegion *region,
int y_amount, int y_amount,
gboolean flip) gboolean flip)
{ {
MetaRegionBuilder builder; MtkRegionBuilder builder;
int n; int n;
int i; int i;
meta_region_builder_init (&builder); mtk_region_builder_init (&builder);
n = mtk_region_num_rectangles (region); n = mtk_region_num_rectangles (region);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
@ -742,7 +741,7 @@ expand_region (MtkRegion *region,
x_amount, y_amount, flip); 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 /* This computes a (clipped version) of the inverse of the region
@ -753,12 +752,12 @@ expand_region_inverse (MtkRegion *region,
int y_amount, int y_amount,
gboolean flip) gboolean flip)
{ {
MetaRegionBuilder builder; MtkRegionBuilder builder;
MtkRegionIterator iter; MtkRegionIterator iter;
MtkRectangle extents; MtkRectangle extents;
int last_x; int last_x;
meta_region_builder_init (&builder); mtk_region_builder_init (&builder);
extents = mtk_region_get_extents (region); extents = mtk_region_get_extents (region);
add_expanded_rect (&builder, 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);
} }
/** /**

View file

@ -44,7 +44,6 @@
#include "cogl/cogl.h" #include "cogl/cogl.h"
#include "compositor/clutter-utils.h" #include "compositor/clutter-utils.h"
#include "compositor/meta-texture-mipmap.h" #include "compositor/meta-texture-mipmap.h"
#include "compositor/region-utils.h"
#include "core/boxes-private.h" #include "core/boxes-private.h"
#include "meta/meta-shaped-texture.h" #include "meta/meta-shaped-texture.h"

View file

@ -31,7 +31,6 @@
#include "backends/meta-screen-cast-window.h" #include "backends/meta-screen-cast-window.h"
#include "compositor/meta-shaped-texture-private.h" #include "compositor/meta-shaped-texture-private.h"
#include "compositor/meta-window-actor-private.h" #include "compositor/meta-window-actor-private.h"
#include "compositor/region-utils.h"
#include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-buffer.h"
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-subsurface.h" #include "wayland/meta-wayland-subsurface.h"

View file

@ -24,7 +24,6 @@
#include "compositor/meta-cullable.h" #include "compositor/meta-cullable.h"
#include "compositor/meta-shaped-texture-private.h" #include "compositor/meta-shaped-texture-private.h"
#include "compositor/meta-window-actor-private.h" #include "compositor/meta-window-actor-private.h"
#include "compositor/region-utils.h"
#include "meta/meta-shaped-texture.h" #include "meta/meta-shaped-texture.h"
enum enum

View file

@ -24,7 +24,6 @@
#include "compositor/meta-cullable.h" #include "compositor/meta-cullable.h"
#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor-wayland.h"
#include "compositor/meta-window-actor-wayland.h" #include "compositor/meta-window-actor-wayland.h"
#include "compositor/region-utils.h"
#include "meta/meta-window-actor.h" #include "meta/meta-window-actor.h"
#include "wayland/meta-wayland-surface-private.h" #include "wayland/meta-wayland-surface-private.h"
#include "wayland/meta-window-wayland.h" #include "wayland/meta-window-wayland.h"

View file

@ -29,7 +29,6 @@
#include "compositor/meta-shaped-texture-private.h" #include "compositor/meta-shaped-texture-private.h"
#include "compositor/meta-surface-actor.h" #include "compositor/meta-surface-actor.h"
#include "compositor/meta-surface-actor-x11.h" #include "compositor/meta-surface-actor-x11.h"
#include "compositor/region-utils.h"
#include "core/frame.h" #include "core/frame.h"
#include "core/window-private.h" #include "core/window-private.h"
#include "meta/compositor.h" #include "meta/compositor.h"
@ -705,9 +704,9 @@ scan_visible_region (guchar *mask_data,
MtkRegion *scan_area) MtkRegion *scan_area)
{ {
int i, n_rects = mtk_region_num_rectangles (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++) for (i = 0; i < n_rects; i++)
{ {
@ -726,14 +725,14 @@ scan_visible_region (guchar *mask_data,
if (x2 > x) 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; x = x2;
} }
} }
} }
} }
return meta_region_builder_finish (&builder); return mtk_region_builder_finish (&builder);
} }
static void static void

View file

@ -9,7 +9,6 @@
#include "compositor/meta-cullable.h" #include "compositor/meta-cullable.h"
#include "compositor/meta-window-actor-private.h" #include "compositor/meta-window-actor-private.h"
#include "compositor/meta-window-group-private.h" #include "compositor/meta-window-group-private.h"
#include "compositor/region-utils.h"
#include "core/display-private.h" #include "core/display-private.h"
#include "core/window-private.h" #include "core/window-private.h"

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "backends/meta-monitor-transform.h"
#include "compositor/region-utils.h"
#include "core/boxes-private.h"
#include <math.h>
/* 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;
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#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);

View file

@ -334,8 +334,6 @@ mutter_sources = [
'compositor/meta-window-group.c', 'compositor/meta-window-group.c',
'compositor/meta-window-group-private.h', 'compositor/meta-window-group-private.h',
'compositor/meta-window-shape.c', 'compositor/meta-window-shape.c',
'compositor/region-utils.c',
'compositor/region-utils.h',
'core/bell.c', 'core/bell.c',
'core/bell.h', 'core/bell.h',
'core/boxes.c', 'core/boxes.c',

View file

@ -38,7 +38,6 @@
#include "backends/meta-backend-private.h" #include "backends/meta-backend-private.h"
#include "backends/meta-pointer-constraint.h" #include "backends/meta-pointer-constraint.h"
#include "compositor/region-utils.h"
#include "wayland/meta-wayland-pointer-constraints.h" #include "wayland/meta-wayland-pointer-constraints.h"
#include "wayland/meta-wayland-pointer.h" #include "wayland/meta-wayland-pointer.h"
#include "wayland/meta-wayland-seat.h" #include "wayland/meta-wayland-seat.h"

View file

@ -25,7 +25,6 @@
#include "backends/meta-logical-monitor.h" #include "backends/meta-logical-monitor.h"
#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor-wayland.h"
#include "compositor/meta-window-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-buffer.h"
#include "wayland/meta-wayland-surface-private.h" #include "wayland/meta-wayland-surface-private.h"
#include "wayland/meta-window-wayland.h" #include "wayland/meta-window-wayland.h"

View file

@ -31,7 +31,7 @@
#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor-wayland.h"
#include "compositor/meta-surface-actor.h" #include "compositor/meta-surface-actor.h"
#include "compositor/meta-window-actor-private.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/display-private.h"
#include "core/window-private.h" #include "core/window-private.h"
#include "wayland/meta-wayland-actor-surface.h" #include "wayland/meta-wayland-actor-surface.h"