region: Move RegionBuilder to Mtk
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3501>
This commit is contained in:
parent
fced59b33d
commit
2a75661883
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
@ -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',
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user