[mutter] MetaMonitorManagerKms: Split up read_current() into logical chunks
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] MetaMonitorManagerKms: Split up read_current() into logical chunks
- Date: Fri, 12 Aug 2016 07:27:44 +0000 (UTC)
commit 6940169f46bded5cca36040fc195132ca73a6a0d
Author: Jonas Ådahl <jadahl gmail com>
Date: Mon Aug 1 17:25:52 2016 +0800
MetaMonitorManagerKms: Split up read_current() into logical chunks
Instead of reading all the different state in one huge function, split
it up into logical chunks, making it easier to read.
https://bugzilla.gnome.org/show_bug.cgi?id=769505
src/backends/native/meta-monitor-manager-kms.c | 694 ++++++++++++++----------
1 files changed, 406 insertions(+), 288 deletions(-)
---
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 04d96aa..0cf6eec 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -54,7 +54,10 @@ typedef struct {
drmModeEncoderPtr *encoders;
drmModeEncoderPtr current_encoder;
- /* bitmasks of encoder position in the resources array */
+ /*
+ * Bitmasks of encoder position in the resources array (used during clone
+ * setup).
+ */
uint32_t encoder_mask;
uint32_t enc_clone_mask;
@@ -369,6 +372,33 @@ find_meta_mode (MetaMonitorManager *manager,
return NULL;
}
+static void
+init_mode (MetaMonitorMode *mode,
+ drmModeModeInfo *drm_mode,
+ long mode_id)
+{
+ mode->mode_id = mode_id;
+ mode->name = g_strndup (drm_mode->name, DRM_DISPLAY_MODE_LEN);
+ mode->width = drm_mode->hdisplay;
+ mode->height = drm_mode->vdisplay;
+ mode->flags = drm_mode->flags;
+
+ /* Calculate refresh rate in milliHz first for extra precision. */
+ mode->refresh_rate = (drm_mode->clock * 1000000LL) / drm_mode->htotal;
+ mode->refresh_rate += (drm_mode->vtotal / 2);
+ mode->refresh_rate /= drm_mode->vtotal;
+ if (drm_mode->flags & DRM_MODE_FLAG_INTERLACE)
+ mode->refresh_rate *= 2;
+ if (drm_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ mode->refresh_rate /= 2;
+ if (drm_mode->vscan > 1)
+ mode->refresh_rate /= drm_mode->vscan;
+ mode->refresh_rate /= 1000.0;
+
+ mode->driver_private = g_slice_dup (drmModeModeInfo, drm_mode);
+ mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
+}
+
static MetaOutput *
find_output_by_id (MetaOutput *outputs,
unsigned n_outputs,
@@ -580,342 +610,250 @@ init_crtc_rotations (MetaMonitorManager *manager,
}
static void
-meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
+init_crtc (MetaCRTC *crtc,
+ MetaMonitorManager *manager,
+ drmModeCrtc *drm_crtc)
{
- MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
- drmModeRes *resources;
- drmModeEncoder **encoders;
- GHashTable *modes;
- GHashTableIter iter;
- drmModeModeInfo *mode;
- unsigned int i, j, k;
- unsigned int n_actual_outputs;
- int width, height;
- MetaOutput *old_outputs;
- unsigned int n_old_outputs;
+ unsigned int i;
- resources = drmModeGetResources(manager_kms->fd);
- modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);
+ crtc->crtc_id = drm_crtc->crtc_id;
+ crtc->rect.x = drm_crtc->x;
+ crtc->rect.y = drm_crtc->y;
+ crtc->rect.width = drm_crtc->width;
+ crtc->rect.height = drm_crtc->height;
+ crtc->is_dirty = FALSE;
+ crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
+ /* FIXME: implement! */
+ crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
+
+ if (drm_crtc->mode_valid)
+ {
+ for (i = 0; i < manager->n_modes; i++)
+ {
+ if (drm_mode_equal (&drm_crtc->mode, manager->modes[i].driver_private))
+ {
+ crtc->current_mode = &manager->modes[i];
+ break;
+ }
+ }
+ }
- manager->max_screen_width = resources->max_width;
- manager->max_screen_height = resources->max_height;
+ crtc->driver_private = g_new0 (MetaCRTCKms, 1);
+ crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
+}
- manager->power_save_mode = META_POWER_SAVE_ON;
+static void
+init_output (MetaOutput *output,
+ MetaMonitorManager *manager,
+ drmModeConnector *connector,
+ MetaOutput *old_output)
+{
+ MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+ MetaOutputKms *output_kms;
+ GArray *crtcs;
+ GBytes *edid;
+ unsigned int i;
+ unsigned int crtc_mask;
- old_outputs = manager->outputs;
- n_old_outputs = manager->n_outputs;
+ output_kms = g_slice_new0 (MetaOutputKms);
+ output->driver_private = output_kms;
+ output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
- /* Note: we must not free the public structures (output, crtc, monitor
- mode and monitor info) here, they must be kept alive until the API
- users are done with them after we emit monitors-changed, and thus
- are freed by the platform-independent layer. */
- free_resources (manager_kms);
+ output->winsys_id = connector->connector_id;
+ output->name = make_output_name (connector);
+ output->width_mm = connector->mmWidth;
+ output->height_mm = connector->mmHeight;
- manager_kms->n_connectors = resources->count_connectors;
- manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
- for (i = 0; i < manager_kms->n_connectors; i++)
+ switch (connector->subpixel)
{
- drmModeConnector *connector;
+ case DRM_MODE_SUBPIXEL_NONE:
+ output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
+ break;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
+ output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
+ break;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
+ output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
+ break;
+ case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
+ output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
+ break;
+ case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
+ output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
+ break;
+ case DRM_MODE_SUBPIXEL_UNKNOWN:
+ default:
+ output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
+ break;
+ }
- connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
- manager_kms->connectors[i] = connector;
+ output->preferred_mode = NULL;
+ output->n_modes = connector->count_modes;
+ output->modes = g_new0 (MetaMonitorMode *, output->n_modes);
+ for (i = 0; i < output->n_modes; i++) {
+ output->modes[i] = find_meta_mode (manager, &connector->modes[i]);
+ if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED)
+ output->preferred_mode = output->modes[i];
+ }
- if (connector && connector->connection == DRM_MODE_CONNECTED)
- {
- /* Collect all modes for this connector */
- for (j = 0; j < (unsigned)connector->count_modes; j++)
- g_hash_table_add (modes, &connector->modes[j]);
- }
- }
+ if (!output->preferred_mode)
+ output->preferred_mode = output->modes[0];
- encoders = g_new (drmModeEncoder *, resources->count_encoders);
- for (i = 0; i < (unsigned)resources->count_encoders; i++)
- encoders[i] = drmModeGetEncoder (manager_kms->fd, resources->encoders[i]);
+ output_kms->connector = connector;
+ output_kms->n_encoders = connector->count_encoders;
+ output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
- manager->n_modes = g_hash_table_size (modes);
- manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
- g_hash_table_iter_init (&iter, modes);
- i = 0;
- while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode))
+ crtc_mask = ~(unsigned int) 0;
+ for (i = 0; i < output_kms->n_encoders; i++)
{
- MetaMonitorMode *meta_mode;
-
- meta_mode = &manager->modes[i];
-
- meta_mode->mode_id = i;
- meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
- meta_mode->width = mode->hdisplay;
- meta_mode->height = mode->vdisplay;
- meta_mode->flags = mode->flags;
-
- /* Calculate refresh rate in milliHz first for extra precision. */
- meta_mode->refresh_rate = (mode->clock * 1000000LL) / mode->htotal;
- meta_mode->refresh_rate += (mode->vtotal / 2);
- meta_mode->refresh_rate /= mode->vtotal;
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- meta_mode->refresh_rate *= 2;
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- meta_mode->refresh_rate /= 2;
- if (mode->vscan > 1)
- meta_mode->refresh_rate /= mode->vscan;
- meta_mode->refresh_rate /= 1000.0;
-
- meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
- meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
-
- i++;
- }
- g_hash_table_destroy (modes);
+ output_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
+ connector->encoders[i]);
+ if (!output_kms->encoders[i])
+ continue;
- manager->n_crtcs = resources->count_crtcs;
- manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
- width = 0; height = 0;
- for (i = 0; i < (unsigned)resources->count_crtcs; i++)
- {
- drmModeCrtc *crtc;
- MetaCRTC *meta_crtc;
+ /* We only list CRTCs as supported if they are supported by all encoders
+ for this connectors.
- crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);
+ This is what xf86-video-modesetting does (see drmmode_output_init())
+ */
+ crtc_mask &= output_kms->encoders[i]->possible_crtcs;
- meta_crtc = &manager->crtcs[i];
+ if (output_kms->encoders[i]->encoder_id == connector->encoder_id)
+ output_kms->current_encoder = output_kms->encoders[i];
+ }
- meta_crtc->crtc_id = crtc->crtc_id;
- meta_crtc->rect.x = crtc->x;
- meta_crtc->rect.y = crtc->y;
- meta_crtc->rect.width = crtc->width;
- meta_crtc->rect.height = crtc->height;
- meta_crtc->is_dirty = FALSE;
- meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
- /* FIXME: implement! */
- meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
+ crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));
- if (crtc->mode_valid)
+ for (i = 0; i < manager->n_crtcs; i++)
+ {
+ if (crtc_mask & (1 << i))
{
- for (j = 0; j < manager->n_modes; j++)
- {
- if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private))
- {
- meta_crtc->current_mode = &manager->modes[j];
- break;
- }
- }
-
- width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width);
- height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
+ MetaCRTC *crtc = &manager->crtcs[i];
+ g_array_append_val (crtcs, crtc);
}
-
- meta_crtc->driver_private = g_new0 (MetaCRTCKms, 1);
- meta_crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
- find_crtc_properties (manager_kms, meta_crtc);
- init_crtc_rotations (manager, meta_crtc, i);
-
- drmModeFreeCrtc (crtc);
}
- manager->screen_width = width;
- manager->screen_height = height;
-
- manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
- n_actual_outputs = 0;
+ output->n_possible_crtcs = crtcs->len;
+ output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);
- for (i = 0; i < manager_kms->n_connectors; i++)
+ if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
{
- MetaOutput *meta_output, *old_output;
- MetaOutputKms *output_kms;
- drmModeConnector *connector;
- GArray *crtcs;
- unsigned int crtc_mask;
- GBytes *edid;
-
- connector = manager_kms->connectors[i];
- meta_output = &manager->outputs[n_actual_outputs];
-
- if (connector && connector->connection == DRM_MODE_CONNECTED)
- {
- meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
- meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
-
- meta_output->winsys_id = connector->connector_id;
- meta_output->name = make_output_name (connector);
- meta_output->width_mm = connector->mmWidth;
- meta_output->height_mm = connector->mmHeight;
-
- switch (connector->subpixel)
+ for (i = 0; i < manager->n_crtcs; i++)
+ {
+ if (manager->crtcs[i].crtc_id == output_kms->current_encoder->crtc_id)
{
- case DRM_MODE_SUBPIXEL_NONE:
- meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
- break;
- case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
- meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
- break;
- case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
- meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
- break;
- case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
- meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
- break;
- case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
- meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
- break;
- case DRM_MODE_SUBPIXEL_UNKNOWN:
- default:
- meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
+ output->crtc = &manager->crtcs[i];
break;
}
+ }
+ }
+ else
+ {
+ output->crtc = NULL;
+ }
- meta_output->preferred_mode = NULL;
- meta_output->n_modes = connector->count_modes;
- meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
- for (j = 0; j < meta_output->n_modes; j++) {
- meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
- if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED)
- meta_output->preferred_mode = meta_output->modes[j];
- }
-
- if (!meta_output->preferred_mode)
- meta_output->preferred_mode = meta_output->modes[0];
-
- output_kms->connector = connector;
- output_kms->n_encoders = connector->count_encoders;
- output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
-
- crtc_mask = ~(unsigned int)0;
- for (j = 0; j < output_kms->n_encoders; j++)
- {
- output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);
- if (!output_kms->encoders[j])
- continue;
-
- /* We only list CRTCs as supported if they are supported by all encoders
- for this connectors.
-
- This is what xf86-video-modesetting does (see drmmode_output_init())
- */
- crtc_mask &= output_kms->encoders[j]->possible_crtcs;
-
- if (output_kms->encoders[j]->encoder_id == connector->encoder_id)
- output_kms->current_encoder = output_kms->encoders[j];
- }
+ if (old_output)
+ {
+ output->is_primary = old_output->is_primary;
+ output->is_presentation = old_output->is_presentation;
+ }
+ else
+ {
+ output->is_primary = FALSE;
+ output->is_presentation = FALSE;
+ }
- crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));
+ find_connector_properties (manager_kms, output_kms);
+ output->suggested_x = output_kms->suggested_x;
+ output->suggested_y = output_kms->suggested_y;
+ output->hotplug_mode_update = output_kms->hotplug_mode_update;
- for (j = 0; j < manager->n_crtcs; j++)
- {
- if (crtc_mask & (1 << j))
- {
- MetaCRTC *crtc = &manager->crtcs[j];
- g_array_append_val (crtcs, crtc);
- }
- }
+ edid = read_output_edid (manager_kms, output);
+ meta_output_parse_edid (output, edid);
+ g_bytes_unref (edid);
- meta_output->n_possible_crtcs = crtcs->len;
- meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);
+ /* MetaConnectorType matches DRM's connector types */
+ output->connector_type = (MetaConnectorType) connector->connector_type;
- if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
- {
- for (j = 0; j < manager->n_crtcs; j++)
- {
- if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id)
- {
- meta_output->crtc = &manager->crtcs[j];
- break;
- }
- }
- }
- else
- meta_output->crtc = NULL;
+ output->scale = get_output_scale (manager, output);
- old_output = find_output_by_id (old_outputs, n_old_outputs,
- meta_output->winsys_id);
- if (old_output)
- {
- meta_output->is_primary = old_output->is_primary;
- meta_output->is_presentation = old_output->is_presentation;
- }
- else
- {
- meta_output->is_primary = FALSE;
- meta_output->is_presentation = FALSE;
- }
+ output_get_tile_info (manager_kms, output);
- find_connector_properties (manager_kms, output_kms);
- meta_output->suggested_x = output_kms->suggested_x;
- meta_output->suggested_y = output_kms->suggested_y;
- meta_output->hotplug_mode_update = output_kms->hotplug_mode_update;
-
- edid = read_output_edid (manager_kms, meta_output);
- meta_output_parse_edid (meta_output, edid);
- g_bytes_unref (edid);
-
- /* MetaConnectorType matches DRM's connector types */
- meta_output->connector_type = (MetaConnectorType) connector->connector_type;
-
- meta_output->scale = get_output_scale (manager, meta_output);
-
- output_get_tile_info (manager_kms, meta_output);
-
- /* FIXME: backlight is a very driver specific thing unfortunately,
- every DDX does its own thing, and the dumb KMS API does not include it.
-
- For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
- (one for each major HW maker, and then some).
- We can't do the same because we're not root.
- It might be best to leave backlight out of the story and rely on the setuid
- helper in gnome-settings-daemon.
- */
- meta_output->backlight_min = 0;
- meta_output->backlight_max = 0;
- meta_output->backlight = -1;
-
- n_actual_outputs++;
- }
- }
+ /* FIXME: backlight is a very driver specific thing unfortunately,
+ every DDX does its own thing, and the dumb KMS API does not include it.
- manager->n_outputs = n_actual_outputs;
- manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs);
+ For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
+ (one for each major HW maker, and then some).
+ We can't do the same because we're not root.
+ It might be best to leave backlight out of the story and rely on the setuid
+ helper in gnome-settings-daemon.
+ */
+ output->backlight_min = 0;
+ output->backlight_max = 0;
+ output->backlight = -1;
+}
- /* Sort the outputs for easier handling in MetaMonitorConfig */
- qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
+static void
+detect_and_setup_output_clones (MetaMonitorManager *manager,
+ drmModeRes *resources)
+{
+ MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+ drmModeEncoder **encoders;
+ unsigned int i, n_encoders;
- /* Now fix the clones.
- Code mostly inspired by xf86-video-modesetting. */
+ n_encoders = (unsigned int) resources->count_encoders;
+ encoders = g_new (drmModeEncoder *, n_encoders);
+ for (i = 0; i < n_encoders; i++)
+ encoders[i] = drmModeGetEncoder (manager_kms->fd, resources->encoders[i]);
- /* XXX: intel hardware doesn't usually have clones, but I only have laptops with
- intel cards, so this code was never tested! */
+ /*
+ * Setup encoder position mask and encoder clone mask.
+ */
for (i = 0; i < manager->n_outputs; i++)
{
- MetaOutput *meta_output;
+ MetaOutput *output;
MetaOutputKms *output_kms;
+ unsigned int j;
- meta_output = &manager->outputs[i];
- output_kms = meta_output->driver_private;
+ output = &manager->outputs[i];
+ output_kms = output->driver_private;
output_kms->enc_clone_mask = 0xff;
output_kms->encoder_mask = 0;
for (j = 0; j < output_kms->n_encoders; j++)
- {
- for (k = 0; k < (unsigned)resources->count_encoders; k++)
- {
+ {
+ unsigned int k;
+
+ for (k = 0; k < n_encoders; k++)
+ {
if (output_kms->encoders[j] && encoders[k] &&
output_kms->encoders[j]->encoder_id == encoders[k]->encoder_id)
- {
+ {
output_kms->encoder_mask |= (1 << k);
- break;
- }
- }
+ break;
+ }
+ }
output_kms->enc_clone_mask &= output_kms->encoders[j]->possible_clones;
- }
+ }
}
+ for (i = 0; i < (unsigned)resources->count_encoders; i++)
+ drmModeFreeEncoder (encoders[i]);
+ g_free (encoders);
+
+ /*
+ * Setup MetaOutput <-> MetaOutput clone associations.
+ */
for (i = 0; i < manager->n_outputs; i++)
{
- MetaOutput *meta_output;
+ MetaOutput *output;
MetaOutputKms *output_kms;
+ unsigned int j;
- meta_output = &manager->outputs[i];
- output_kms = meta_output->driver_private;
+ output = &manager->outputs[i];
+ output_kms = output->driver_private;
if (output_kms->enc_clone_mask == 0)
continue;
@@ -928,7 +866,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_clone = &manager->outputs[i];
clone_kms = meta_clone->driver_private;
- if (meta_clone == meta_output)
+ if (meta_clone == output)
continue;
if (clone_kms->encoder_mask == 0)
@@ -936,18 +874,198 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
if (clone_kms->encoder_mask == output_kms->enc_clone_mask)
{
- meta_output->n_possible_clones++;
- meta_output->possible_clones = g_renew (MetaOutput *,
- meta_output->possible_clones,
- meta_output->n_possible_clones);
- meta_output->possible_clones[meta_output->n_possible_clones - 1] = meta_clone;
+ output->n_possible_clones++;
+ output->possible_clones = g_renew (MetaOutput *,
+ output->possible_clones,
+ output->n_possible_clones);
+ output->possible_clones[output->n_possible_clones - 1] = meta_clone;
}
}
}
+}
- for (i = 0; i < (unsigned)resources->count_encoders; i++)
- drmModeFreeEncoder (encoders[i]);
- g_free (encoders);
+static void
+init_connectors (MetaMonitorManager *manager,
+ drmModeRes *resources)
+{
+ MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+ unsigned int i;
+
+ manager_kms->n_connectors = resources->count_connectors;
+ manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
+ for (i = 0; i < manager_kms->n_connectors; i++)
+ {
+ drmModeConnector *drm_connector;
+
+ drm_connector = drmModeGetConnector (manager_kms->fd,
+ resources->connectors[i]);
+ manager_kms->connectors[i] = drm_connector;
+ }
+}
+
+static void
+init_modes (MetaMonitorManager *manager,
+ drmModeRes *resources)
+{
+ MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+ GHashTable *modes;
+ GHashTableIter iter;
+ drmModeModeInfo *drm_mode;
+ unsigned int i;
+ long mode_id;
+
+ /*
+ * Gather all modes on all connected connectors.
+ */
+ modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);
+ for (i = 0; i < manager_kms->n_connectors; i++)
+ {
+ drmModeConnector *drm_connector;
+
+ drm_connector = manager_kms->connectors[i];
+ if (drm_connector && drm_connector->connection == DRM_MODE_CONNECTED)
+ {
+ unsigned int j;
+
+ for (j = 0; j < (unsigned int) drm_connector->count_modes; j++)
+ g_hash_table_add (modes, &drm_connector->modes[j]);
+ }
+ }
+
+ manager->n_modes = g_hash_table_size (modes);
+ manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
+
+ g_hash_table_iter_init (&iter, modes);
+ mode_id = 0;
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &drm_mode))
+ {
+ MetaMonitorMode *mode;
+
+ mode = &manager->modes[mode_id];
+ init_mode (mode, drm_mode, (long) mode_id);
+
+ mode_id++;
+ }
+
+ g_hash_table_destroy (modes);
+}
+
+static void
+init_crtcs (MetaMonitorManager *manager,
+ drmModeRes *resources)
+{
+ MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+ unsigned int i;
+
+ manager->n_crtcs = resources->count_crtcs;
+ manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
+
+ for (i = 0; i < (unsigned)resources->count_crtcs; i++)
+ {
+ drmModeCrtc *drm_crtc;
+ MetaCRTC *crtc;
+
+ drm_crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);
+
+ crtc = &manager->crtcs[i];
+
+ init_crtc (crtc, manager, drm_crtc);
+ find_crtc_properties (manager_kms, crtc);
+ init_crtc_rotations (manager, crtc, i);
+
+ drmModeFreeCrtc (drm_crtc);
+ }
+}
+
+static void
+init_outputs (MetaMonitorManager *manager,
+ drmModeRes *resources)
+{
+ MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+ MetaOutput *old_outputs;
+ unsigned int n_old_outputs;
+ unsigned int n_actual_outputs;
+ unsigned int i;
+
+ old_outputs = manager->outputs;
+ n_old_outputs = manager->n_outputs;
+
+ manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
+ n_actual_outputs = 0;
+
+ for (i = 0; i < manager_kms->n_connectors; i++)
+ {
+ drmModeConnector *connector;
+ MetaOutput *output;
+
+ connector = manager_kms->connectors[i];
+ output = &manager->outputs[n_actual_outputs];
+
+ if (connector && connector->connection == DRM_MODE_CONNECTED)
+ {
+ MetaOutput *old_output;
+
+ old_output = find_output_by_id (old_outputs, n_old_outputs,
+ output->winsys_id);
+ init_output (output, manager, connector, old_output);
+ n_actual_outputs++;
+ }
+ }
+
+ manager->n_outputs = n_actual_outputs;
+ manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs);
+
+ /* Sort the outputs for easier handling in MetaMonitorConfig */
+ qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput),
+ compare_outputs);
+
+ detect_and_setup_output_clones (manager, resources);
+}
+
+static void
+calculate_screen_size (MetaMonitorManager *manager)
+{
+ unsigned int i;
+ int width = 0, height = 0;
+
+ for (i = 0; i < manager->n_crtcs; i++)
+ {
+ MetaCRTC *crtc = &manager->crtcs[i];
+
+ width = MAX (width, crtc->rect.x + crtc->rect.width);
+ height = MAX (height, crtc->rect.y + crtc->rect.height);
+ }
+
+ manager->screen_width = width;
+ manager->screen_height = height;
+}
+
+static void
+meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
+{
+ MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+ drmModeRes *resources;
+
+ resources = drmModeGetResources(manager_kms->fd);
+
+ /* TODO: max screen width only matters for stage views is not enabled. */
+ manager->max_screen_width = resources->max_width;
+ manager->max_screen_height = resources->max_height;
+
+ manager->power_save_mode = META_POWER_SAVE_ON;
+
+ /* Note: we must not free the public structures (output, crtc, monitor
+ mode and monitor info) here, they must be kept alive until the API
+ users are done with them after we emit monitors-changed, and thus
+ are freed by the platform-independent layer. */
+ free_resources (manager_kms);
+
+ init_connectors (manager, resources);
+ init_modes (manager, resources);
+ init_crtcs (manager, resources);
+ init_outputs (manager, resources);
+
+ calculate_screen_size (manager);
drmModeFreeResources (resources);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]