monitor-manager: Generate logical monitors from monitors

Instead of using crtcs and outputs to generate logical monitors, use
the ready made monitor abstraction that hides irrelevant things such as
monitor tiling etc.

https://bugzilla.gnome.org/show_bug.cgi?id=777732
This commit is contained in:
Jonas Ådahl 2016-12-13 11:03:22 +08:00
parent f48acd8448
commit bf8b4e9927
5 changed files with 193 additions and 197 deletions

View File

@ -25,6 +25,105 @@
G_DEFINE_TYPE (MetaLogicalMonitor, meta_logical_monitor, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaLogicalMonitor, meta_logical_monitor, G_TYPE_OBJECT)
MetaLogicalMonitor *
meta_logical_monitor_new (MetaMonitor *monitor,
int x,
int y,
int number)
{
MetaLogicalMonitor *logical_monitor;
MetaOutput *main_output;
GList *outputs;
GList *l;
gboolean is_presentation;
int i;
g_assert (meta_monitor_is_active (monitor));
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL);
main_output = meta_monitor_get_main_output (monitor);
logical_monitor->number = number;
logical_monitor->refresh_rate = main_output->crtc->current_mode->refresh_rate;
logical_monitor->width_mm = main_output->width_mm;
logical_monitor->height_mm = main_output->height_mm;
logical_monitor->winsys_id = main_output->winsys_id;
logical_monitor->scale = main_output->scale;
logical_monitor->in_fullscreen = -1;
logical_monitor->rect.x = x;
logical_monitor->rect.y = y;
meta_monitor_get_dimensions (monitor,
&logical_monitor->rect.width,
&logical_monitor->rect.height);
is_presentation = TRUE;
outputs = meta_monitor_get_outputs (monitor);
for (l = outputs, i = 0; l; l = l->next, i++)
{
MetaOutput *output = l->data;
output->crtc->logical_monitor = logical_monitor;
if (i <= META_MAX_OUTPUTS_PER_MONITOR)
logical_monitor->outputs[i] = output;
else
g_warning ("Couldn't add all outputs to monitor");
is_presentation = is_presentation && output->is_presentation;
}
logical_monitor->n_outputs = MIN (i, META_MAX_OUTPUTS_PER_MONITOR);
logical_monitor->is_presentation = is_presentation;
logical_monitor->monitors = g_list_append (logical_monitor->monitors,
monitor);
return logical_monitor;
}
void
meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
MetaMonitor *monitor)
{
GList *outputs;
GList *l;
gboolean is_presentation;
int i;
is_presentation = logical_monitor->is_presentation;
logical_monitor->monitors = g_list_append (logical_monitor->monitors,
monitor);
outputs = meta_monitor_get_outputs (monitor);
for (l = outputs, i = logical_monitor->n_outputs; l; l = l->next, i++)
{
MetaOutput *output = l->data;
output->crtc->logical_monitor = logical_monitor;
if (i <= META_MAX_OUTPUTS_PER_MONITOR)
logical_monitor->outputs[i] = output;
else
g_warning ("Couldn't add all outputs to monitor");
is_presentation = is_presentation && output->is_presentation;
}
logical_monitor->n_outputs = MIN (i, META_MAX_OUTPUTS_PER_MONITOR);
logical_monitor->is_presentation = is_presentation;
}
gboolean
meta_logical_monitor_is_primary (MetaLogicalMonitor *logical_monitor)
{
return logical_monitor->is_primary;
}
void
meta_logical_monitor_make_primary (MetaLogicalMonitor *logical_monitor)
{
logical_monitor->is_primary = TRUE;
}
static void static void
meta_logical_monitor_init (MetaLogicalMonitor *logical_monitor) meta_logical_monitor_init (MetaLogicalMonitor *logical_monitor)
{ {

View File

@ -24,6 +24,7 @@
#include <glib-object.h> #include <glib-object.h>
#include "backends/meta-monitor.h"
#include "backends/meta-monitor-manager-private.h" #include "backends/meta-monitor-manager-private.h"
#include "meta/boxes.h" #include "meta/boxes.h"
@ -54,11 +55,11 @@ struct _MetaLogicalMonitor
*/ */
glong winsys_id; glong winsys_id;
guint32 tile_group_id;
int monitor_winsys_xid; int monitor_winsys_xid;
int n_outputs; int n_outputs;
MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR]; MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR];
GList *monitors;
}; };
#define META_TYPE_LOGICAL_MONITOR (meta_logical_monitor_get_type ()) #define META_TYPE_LOGICAL_MONITOR (meta_logical_monitor_get_type ())
@ -66,4 +67,16 @@ G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor,
META, LOGICAL_MONITOR, META, LOGICAL_MONITOR,
GObject) GObject)
MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitor *monitor,
int x,
int y,
int number);
void meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
MetaMonitor *monitor);
gboolean meta_logical_monitor_is_primary (MetaLogicalMonitor *logical_monitor);
void meta_logical_monitor_make_primary (MetaLogicalMonitor *logical_monitor);
#endif /* META_LOGICAL_MONITOR_H */ #endif /* META_LOGICAL_MONITOR_H */

View File

@ -73,227 +73,94 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
{ {
} }
static void
meta_monitor_manager_set_primary_logical_monitor (MetaMonitorManager *manager,
MetaLogicalMonitor *logical_monitor)
{
manager->primary_logical_monitor = logical_monitor;
if (logical_monitor)
meta_logical_monitor_make_primary (logical_monitor);
}
static gboolean static gboolean
is_main_tiled_monitor_output (MetaOutput *output) is_main_tiled_monitor_output (MetaOutput *output)
{ {
return output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0; return output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0;
} }
static void
calculate_tiled_monitor_size (MetaMonitorManager *manager,
uint32_t tile_group_id,
int *out_width,
int *out_height)
{
int width, height;
unsigned int i;
width = 0;
height = 0;
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->tile_info.group_id != tile_group_id)
continue;
if (output->tile_info.loc_v_tile == 0)
width += output->tile_info.tile_w;
if (output->tile_info.loc_h_tile == 0)
height += output->tile_info.tile_h;
}
*out_width = width;
*out_height = height;
}
static void
add_tiled_monitor_outputs (MetaMonitorManager *manager,
MetaLogicalMonitor *logical_monitor,
uint32_t tile_group_id)
{
unsigned int i;
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->tile_info.group_id != tile_group_id)
continue;
if (logical_monitor->n_outputs > META_MAX_OUTPUTS_PER_MONITOR)
{
g_warning ("Couldn't add all outputs to monitor");
return;
}
logical_monitor->outputs[logical_monitor->n_outputs] = output;
logical_monitor->n_outputs++;
}
}
static MetaLogicalMonitor * static MetaLogicalMonitor *
construct_tile_monitor (MetaMonitorManager *manager, logical_monitor_from_layout (MetaMonitorManager *manager,
MetaOutput *output, GList *logical_monitors,
int monitor_number) MetaRectangle *layout)
{ {
MetaLogicalMonitor *logical_monitor = NULL;
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL);
logical_monitor->tile_group_id = output->tile_info.group_id;
logical_monitor->refresh_rate = output->crtc->current_mode->refresh_rate;
logical_monitor->width_mm = output->width_mm;
logical_monitor->height_mm = output->height_mm;
logical_monitor->winsys_id = output->winsys_id;
logical_monitor->scale = output->scale;
logical_monitor->rect.x = output->crtc->rect.x;
logical_monitor->rect.y = output->crtc->rect.y;
calculate_tiled_monitor_size (manager, output->tile_info.group_id,
&logical_monitor->rect.width,
&logical_monitor->rect.height);
add_tiled_monitor_outputs (manager, logical_monitor,
output->tile_info.group_id);
return logical_monitor;
}
/*
* make_logical_config:
*
* Turn outputs and CRTCs into logical MetaLogicalMonitor,
* that will be used by the core and API layer (MetaScreen
* and friends)
*/
static void
make_logical_config (MetaMonitorManager *manager)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
GList *logical_monitors = NULL;
int monitor_number;
unsigned int i;
monitor_number = 0;
/* Walk the list of MetaCrtcs, and build a MetaLogicalMonitor
for each of them, unless they reference a rectangle that
is already there.
*/
/* for tiling we need to work out how many tiled outputs there are */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (!output->crtc)
continue;
if (!output->tile_info.group_id)
continue;
if (is_main_tiled_monitor_output (output))
{
MetaLogicalMonitor *logical_monitor;
logical_monitor = construct_tile_monitor (manager,
output,
monitor_number);
logical_monitors = g_list_append (logical_monitors, logical_monitor);
monitor_number++;
}
}
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCrtc *crtc = &manager->crtcs[i];
GList *l; GList *l;
/* Ignore CRTCs not in use */
if (crtc->current_mode == NULL)
continue;
for (l = logical_monitors; l; l = l->next) for (l = logical_monitors; l; l = l->next)
{ {
MetaLogicalMonitor *logical_monitor = l->data; MetaLogicalMonitor *logical_monitor = l->data;
if (meta_rectangle_contains_rect (&logical_monitor->rect, if (meta_rectangle_equal (layout, &logical_monitor->rect))
&crtc->rect)) return logical_monitor;
{
crtc->logical_monitor = logical_monitor;
break;
}
} }
if (crtc->logical_monitor == NULL) return NULL;
}
static void
derive_monitor_position (MetaMonitor *monitor,
int *x,
int *y)
{ {
MetaOutput *main_output;
main_output = meta_monitor_get_main_output (monitor);
*x = main_output->crtc->rect.x;
*y = main_output->crtc->rect.y;
}
static void
make_logical_config (MetaMonitorManager *manager)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
GList *logical_monitors = NULL;
GList *l;
int monitor_number;
MetaLogicalMonitor *primary_logical_monitor = NULL;
monitor_number = 0;
for (l = manager->monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
MetaLogicalMonitor *logical_monitor; MetaLogicalMonitor *logical_monitor;
MetaRectangle layout;
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); if (!meta_monitor_is_active (monitor))
continue;
logical_monitor->number = monitor_number; derive_monitor_position (monitor, &layout.x, &layout.y);
logical_monitor->rect = crtc->rect; meta_monitor_get_dimensions (monitor, &layout.width, &layout.height);
logical_monitor->refresh_rate = crtc->current_mode->refresh_rate; logical_monitor = logical_monitor_from_layout (manager, logical_monitors,
logical_monitor->scale = 1; &layout);
logical_monitor->is_primary = FALSE; if (logical_monitor)
/* This starts true because we want {
is_presentation only if all outputs are meta_logical_monitor_add_monitor (logical_monitor, monitor);
marked as such (while for primary it's enough }
that any is marked) else
*/ {
logical_monitor->is_presentation = TRUE; int x, y;
logical_monitor->in_fullscreen = -1;
derive_monitor_position (monitor, &x, &y);
logical_monitor = meta_logical_monitor_new (monitor,
x, y,
monitor_number);
logical_monitors = g_list_append (logical_monitors, logical_monitor); logical_monitors = g_list_append (logical_monitors, logical_monitor);
monitor_number++; monitor_number++;
crtc->logical_monitor = logical_monitor;
}
} }
/* Now walk the list of outputs applying extended properties (primary if (meta_monitor_is_primary (monitor))
and presentation) primary_logical_monitor = logical_monitor;
*/
manager->primary_logical_monitor = NULL;
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output;
MetaLogicalMonitor *logical_monitor;
output = &manager->outputs[i];
/* Ignore outputs that are not active */
if (output->crtc == NULL)
continue;
if (output->tile_info.group_id)
continue;
/* We must have a logical monitor on every CRTC at this point */
g_assert (output->crtc->logical_monitor != NULL);
logical_monitor = output->crtc->logical_monitor;
logical_monitor->is_primary =
logical_monitor->is_primary || output->is_primary;
logical_monitor->is_presentation =
logical_monitor->is_presentation && output->is_presentation;
logical_monitor->width_mm = output->width_mm;
logical_monitor->height_mm = output->height_mm;
logical_monitor->outputs[0] = output;
logical_monitor->n_outputs = 1;
logical_monitor->scale = output->scale;
if (output->is_primary || logical_monitor->winsys_id == 0)
logical_monitor->winsys_id = output->winsys_id;
if (logical_monitor->is_primary)
manager->primary_logical_monitor = logical_monitor;
} }
manager->logical_monitors = logical_monitors; manager->logical_monitors = logical_monitors;
@ -302,8 +169,11 @@ make_logical_config (MetaMonitorManager *manager)
* If no monitor was marked as primary, fall back on marking the first * If no monitor was marked as primary, fall back on marking the first
* logical monitor the primary one. * logical monitor the primary one.
*/ */
if (!manager->primary_logical_monitor && manager->logical_monitors) if (!primary_logical_monitor && manager->logical_monitors)
manager->primary_logical_monitor = g_list_first (manager->logical_monitors)->data; primary_logical_monitor = g_list_first (manager->logical_monitors)->data;
meta_monitor_manager_set_primary_logical_monitor (manager,
primary_logical_monitor);
if (manager_class->add_monitor) if (manager_class->add_monitor)
{ {

View File

@ -69,7 +69,7 @@ meta_monitor_get_outputs (MetaMonitor *monitor)
return priv->outputs; return priv->outputs;
} }
static MetaOutput * MetaOutput *
meta_monitor_get_main_output (MetaMonitor *monitor) meta_monitor_get_main_output (MetaMonitor *monitor)
{ {
return META_MONITOR_GET_CLASS (monitor)->get_main_output (monitor); return META_MONITOR_GET_CLASS (monitor)->get_main_output (monitor);
@ -85,6 +85,16 @@ meta_monitor_is_active (MetaMonitor *monitor)
return output->crtc && output->crtc->current_mode; return output->crtc && output->crtc->current_mode;
} }
gboolean
meta_monitor_is_primary (MetaMonitor *monitor)
{
MetaOutput *output;
output = meta_monitor_get_main_output (monitor);
return output->is_primary;
}
void void
meta_monitor_get_dimensions (MetaMonitor *monitor, meta_monitor_get_dimensions (MetaMonitor *monitor,
int *width, int *width,

View File

@ -56,6 +56,10 @@ MetaMonitorNormal * meta_monitor_normal_new (MetaOutput *output);
gboolean meta_monitor_is_active (MetaMonitor *monitor); gboolean meta_monitor_is_active (MetaMonitor *monitor);
MetaOutput * meta_monitor_get_main_output (MetaMonitor *monitor);
gboolean meta_monitor_is_primary (MetaMonitor *monitor);
GList * meta_monitor_get_outputs (MetaMonitor *monitor); GList * meta_monitor_get_outputs (MetaMonitor *monitor);
void meta_monitor_get_dimensions (MetaMonitor *monitor, void meta_monitor_get_dimensions (MetaMonitor *monitor,