compositor-drm: Track unused connectors and CRTCs

Rather than a more piecemeal approach at backend creation, explicitly
track connectors and CRTCs we do not intend to use, so we can ensure
they are disabled where appropriate.

When we have an updated list of connector and CRTC IDs, we add any which
are not owned by an enabled drm_output to the list. We remove them from
the list when drm_output_repaint() is called for that output, and re-add
them when the output is disabled or destroyed.

Signed-off-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
dev
Daniel Stone 8 years ago
parent 85f8432911
commit 087ddf04e2
  1. 89
      libweston/compositor-drm.c

@ -188,6 +188,10 @@ struct drm_backend {
void *repaint_data;
/* Connector and CRTC IDs not used by any enabled output. */
struct wl_array unused_connectors;
struct wl_array unused_crtcs;
int cursors_are_broken;
bool universal_planes;
@ -386,6 +390,26 @@ static struct gl_renderer_interface *gl_renderer;
static const char default_seat[] = "seat0";
static void
wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
{
uint32_t *pos, *end;
end = (uint32_t *) ((char *) array->data + array->size);
wl_array_for_each(pos, array) {
if (*pos != elm)
continue;
array->size -= sizeof(*pos);
if (pos + 1 == end)
break;
memmove(pos, pos + 1, (char *) end - (char *) (pos + 1));
break;
}
}
static inline struct drm_output *
to_drm_output(struct weston_output *base)
{
@ -1694,7 +1718,6 @@ drm_output_repaint(struct weston_output *output_base,
pending_state,
DRM_OUTPUT_STATE_CLEAR_PLANES);
/* If disable_planes is set then assign_planes() wasn't
* called for this render, so we could still have a stale
* cursor plane set up.
@ -1710,6 +1733,10 @@ drm_output_repaint(struct weston_output *output_base,
if (!scanout_state || !scanout_state->fb)
goto err;
wl_array_remove_uint32(&backend->unused_connectors,
output->connector_id);
wl_array_remove_uint32(&backend->unused_crtcs, output->crtc_id);
/* The legacy SetCrtc API doesn't allow us to do scaling, and the
* legacy PageFlip API doesn't allow us to do clipping either. */
assert(scanout_state->src_x == 0);
@ -3989,6 +4016,7 @@ drm_output_deinit(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
struct drm_backend *b = to_drm_backend(base->compositor);
uint32_t *unused;
if (b->use_pixman)
drm_output_fini_pixman(output);
@ -4010,6 +4038,11 @@ drm_output_deinit(struct weston_output *base)
drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
}
}
unused = wl_array_add(&b->unused_connectors, sizeof(*unused));
*unused = output->connector_id;
unused = wl_array_add(&b->unused_crtcs, sizeof(*unused));
*unused = output->crtc_id;
}
static void
@ -4105,6 +4138,51 @@ drm_output_disable(struct weston_output *base)
return 0;
}
/**
* Update the list of unused connectors and CRTCs
*
* This keeps the unused_connectors and unused_crtcs arrays up to date.
*
* @param b Weston backend structure
* @param resources DRM resources for this device
*/
static void
drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
{
int i;
wl_array_release(&b->unused_connectors);
wl_array_init(&b->unused_connectors);
for (i = 0; i < resources->count_connectors; i++) {
struct drm_output *output;
uint32_t *connector_id;
output = drm_output_find_by_connector(b, resources->connectors[i]);
if (output && output->base.enabled)
continue;
connector_id = wl_array_add(&b->unused_connectors,
sizeof(*connector_id));
*connector_id = resources->connectors[i];
}
wl_array_release(&b->unused_crtcs);
wl_array_init(&b->unused_crtcs);
for (i = 0; i < resources->count_crtcs; i++) {
struct drm_output *output;
uint32_t *crtc_id;
output = drm_output_find_by_crtc(b, resources->crtcs[i]);
if (output && output->base.enabled)
continue;
crtc_id = wl_array_add(&b->unused_crtcs, sizeof(*crtc_id));
*crtc_id = resources->crtcs[i];
}
}
/**
* Create a Weston output structure
*
@ -4265,6 +4343,8 @@ create_outputs(struct drm_backend *b, struct udev_device *drm_device)
}
}
drm_backend_update_unused_outputs(b, resources);
if (wl_list_empty(&b->compositor->output_list) &&
wl_list_empty(&b->compositor->pending_output_list))
weston_log("No currently active connector found.\n");
@ -4356,6 +4436,8 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
drm_output_destroy(&output->base);
}
drm_backend_update_unused_outputs(b, resources);
free(connected);
drmModeFreeResources(resources);
}
@ -4422,6 +4504,9 @@ drm_destroy(struct weston_compositor *ec)
weston_launcher_destroy(ec->launcher);
wl_array_release(&b->unused_crtcs);
wl_array_release(&b->unused_connectors);
close(b->drm.fd);
free(b);
}
@ -4854,6 +4939,8 @@ drm_backend_create(struct weston_compositor *compositor,
return NULL;
b->drm.fd = -1;
wl_array_init(&b->unused_crtcs);
wl_array_init(&b->unused_connectors);
/*
* KMS support for hardware planes cannot properly synchronize

Loading…
Cancel
Save