From ea2496c80a72b882b5b2a3f6eca2ca11d59c25ca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 31 Mar 2015 11:08:34 +1000 Subject: [PATCH] monitors: construct tiled monitors info The monitors info structure is created from the tiled outputs and this is used as the central storage for info about a monitor as opposed to the output state. It appears at least the EDID mm w/h is for the whole monitor and not per tile. --- src/backends/meta-monitor-manager-private.h | 11 ++ src/backends/meta-monitor-manager.c | 119 +++++++++++++++++++- 2 files changed, 127 insertions(+), 3 deletions(-) diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index efbca28a8..c5444d623 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -193,6 +193,7 @@ struct _MetaMonitorMode GDestroyNotify driver_notify; }; +#define META_MAX_OUTPUTS_PER_MONITOR 4 /** * MetaMonitorInfo: * @@ -208,6 +209,10 @@ struct _MetaMonitorInfo int number; int xinerama_index; MetaRectangle rect; + /* for tiled monitors these are calculated, from untiled just copied */ + float refresh_rate; + int width_mm; + int height_mm; gboolean is_primary; gboolean is_presentation; /* XXX: not yet used */ gboolean in_fullscreen; @@ -221,6 +226,12 @@ struct _MetaMonitorInfo the primary one). */ glong winsys_id; + + guint32 tile_group_id; + + int monitor_winsys_xid; + int n_outputs; + MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR]; }; /* diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 029c214e3..89efaca82 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -71,6 +71,98 @@ meta_monitor_manager_init (MetaMonitorManager *manager) { } +/* + * rules for constructing a tiled monitor + * 1. find a tile_group_id + * 2. iterate over all outputs for that tile group id + * 3. see if output has a crtc and if it is configured for the tile size + * 4. calculate the total tile size + * 5. set tile finished size + * 6. check for more tile_group_id +*/ +static void +construct_tile_monitor (MetaMonitorManager *manager, + GArray *monitor_infos, + guint32 tile_group_id) +{ + MetaMonitorInfo info; + unsigned i; + + for (i = 0; i < monitor_infos->len; i++) + { + MetaMonitorInfo *pinfo = &g_array_index (monitor_infos, MetaMonitorInfo, i); + + if (pinfo->tile_group_id == tile_group_id) + return; + } + + /* didn't find it */ + info.number = monitor_infos->len; + info.tile_group_id = tile_group_id; + info.is_presentation = FALSE; + info.refresh_rate = 0.0; + info.width_mm = 0; + info.height_mm = 0; + info.is_primary = FALSE; + info.rect.x = INT_MAX; + info.rect.y = INT_MAX; + info.rect.width = 0; + info.rect.height = 0; + info.winsys_id = 0; + info.n_outputs = 0; + info.monitor_winsys_xid = 0; + + for (i = 0; i < manager->n_outputs; i++) + { + MetaOutput *output = &manager->outputs[i]; + + if (!output->tile_info.group_id) + continue; + + if (output->tile_info.group_id != tile_group_id) + continue; + + if (!output->crtc) + continue; + + if (output->crtc->rect.width != (int)output->tile_info.tile_w || + output->crtc->rect.height != (int)output->tile_info.tile_h) + continue; + + if (output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0) + { + info.refresh_rate = output->crtc->current_mode->refresh_rate; + info.width_mm = output->width_mm; + info.height_mm = output->height_mm; + info.winsys_id = output->winsys_id; + } + + /* hack */ + if (output->crtc->rect.x < info.rect.x) + info.rect.x = output->crtc->rect.x; + if (output->crtc->rect.y < info.rect.y) + info.rect.y = output->crtc->rect.y; + + if (output->tile_info.loc_h_tile == 0) + info.rect.height += output->tile_info.tile_h; + + if (output->tile_info.loc_v_tile == 0) + info.rect.width += output->tile_info.tile_w; + + if (info.n_outputs > META_MAX_OUTPUTS_PER_MONITOR) + continue; + + info.outputs[info.n_outputs++] = output; + } + + /* if we don't have a winsys id, i.e. we haven't found tile 0,0 + don't try and add this to the monitor infos */ + if (!info.winsys_id) + return; + + g_array_append_val (monitor_infos, info); +} + /* * make_logical_config: * @@ -91,6 +183,15 @@ make_logical_config (MetaMonitorManager *manager) 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->tile_info.group_id) + construct_tile_monitor (manager, monitor_infos, output->tile_info.group_id); + } + for (i = 0; i < manager->n_crtcs; i++) { MetaCRTC *crtc = &manager->crtcs[i]; @@ -102,8 +203,8 @@ make_logical_config (MetaMonitorManager *manager) for (j = 0; j < monitor_infos->len; j++) { MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j); - if (meta_rectangle_equal (&crtc->rect, - &info->rect)) + if (meta_rectangle_contains_rect (&info->rect, + &crtc->rect)) { crtc->logical_monitor = info; break; @@ -115,7 +216,9 @@ make_logical_config (MetaMonitorManager *manager) MetaMonitorInfo info; info.number = monitor_infos->len; + info.tile_group_id = 0; info.rect = crtc->rect; + info.refresh_rate = crtc->current_mode->refresh_rate; info.is_primary = FALSE; /* This starts true because we want is_presentation only if all outputs are @@ -125,7 +228,8 @@ make_logical_config (MetaMonitorManager *manager) info.is_presentation = TRUE; info.in_fullscreen = -1; info.winsys_id = 0; - + info.n_outputs = 0; + info.monitor_winsys_xid = 0; g_array_append_val (monitor_infos, info); crtc->logical_monitor = &g_array_index (monitor_infos, MetaMonitorInfo, @@ -147,6 +251,9 @@ make_logical_config (MetaMonitorManager *manager) 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); @@ -155,6 +262,12 @@ make_logical_config (MetaMonitorManager *manager) info->is_primary = info->is_primary || output->is_primary; info->is_presentation = info->is_presentation && output->is_presentation; + info->width_mm = output->width_mm; + info->height_mm = output->height_mm; + + info->outputs[0] = output; + info->n_outputs = 1; + if (output->is_primary || info->winsys_id == 0) info->winsys_id = output->winsys_id;