From 663d5e9b12b96d670bd598afcc4d5921c827492a Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 8 Sep 2017 13:32:40 +0300 Subject: [PATCH] compositor-drm: allocate CRTC on enable() A drm_output needs a CRTC only when it is in use. Allocating a CRTC on creation of drm_output will reserve the CRTC regardless of whether the output is actually used or not. This may cause creating other drm_outputs to fail if there are not enough CRTCs. Instead, allocate the CRTC on drm_output enable() time. A drm_output will have a valid CRTC only while it is enabled. This allows us to create drm_output objects arbitrarily and without a head assignment, which is required by the head-based output API for the backends. The assigned heads will be known only at enable() time. Now drm_output_enable() has to call drmModeGetResources() to be able to find a suitable CRTC. We might want to cache the resources somewhere, but that is it topic for another patch. v4: Force resetting unused CRTCs on fini. Signed-off-by: Pekka Paalanen Reviewed-by: Daniel Stone Acked-by: Derek Foreman --- libweston/compositor-drm.c | 43 ++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 701a40c21..90c6f24da 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -4698,6 +4698,8 @@ drm_output_init_crtc(struct drm_output *output, drm_output_find_special_plane(b, output, WDRM_PLANE_TYPE_CURSOR); + wl_array_remove_uint32(&b->unused_crtcs, output->crtc_id); + return 0; err_crtc: @@ -4717,6 +4719,7 @@ static void drm_output_fini_crtc(struct drm_output *output) { struct drm_backend *b = to_drm_backend(output->base.compositor); + uint32_t *unused; if (!b->universal_planes && !b->shutting_down) { /* With universal planes, the 'special' planes are allocated at @@ -4738,6 +4741,15 @@ drm_output_fini_crtc(struct drm_output *output) } drm_property_info_free(output->props_crtc, WDRM_CRTC__COUNT); + + assert(output->crtc_id != 0); + + unused = wl_array_add(&b->unused_crtcs, sizeof(*unused)); + *unused = output->crtc_id; + + /* Force resetting unused CRTCs */ + b->state_invalid = true; + output->crtc_id = 0; output->cursor_plane = NULL; output->scanout_plane = NULL; @@ -4750,6 +4762,21 @@ drm_output_enable(struct weston_output *base) struct drm_backend *b = to_drm_backend(base->compositor); struct drm_head *head = to_drm_head(weston_output_get_first_head(base)); struct weston_mode *m; + drmModeRes *resources; + int ret; + + resources = drmModeGetResources(b->drm.fd); + if (!resources) { + weston_log("drmModeGetResources failed\n"); + return -1; + } + ret = drm_output_init_crtc(output, resources, head->connector); + drmModeFreeResources(resources); + if (ret < 0) + return -1; + + if (drm_output_init_gamma_size(output) < 0) + goto err; if (b->pageflip_timeout) drm_output_pageflip_timer_create(output); @@ -4792,7 +4819,6 @@ drm_output_enable(struct weston_output *base) &b->compositor->primary_plane); wl_array_remove_uint32(&b->unused_connectors, head->connector_id); - wl_array_remove_uint32(&b->unused_crtcs, output->crtc_id); weston_log("Output %s, (connector %d, crtc %d)\n", output->base.name, head->connector_id, output->crtc_id); @@ -4809,6 +4835,8 @@ drm_output_enable(struct weston_output *base) return 0; err: + drm_output_fini_crtc(output); + return -1; } @@ -4843,11 +4871,8 @@ drm_output_deinit(struct weston_output *base) unused = wl_array_add(&b->unused_connectors, sizeof(*unused)); *unused = head->connector_id; - unused = wl_array_add(&b->unused_crtcs, sizeof(*unused)); - *unused = output->crtc_id; - /* Force programming unused connectors and crtcs. */ - b->state_invalid = true; + drm_output_fini_crtc(output); } static void @@ -4877,8 +4902,6 @@ drm_output_destroy(struct weston_output *base) weston_output_release(&output->base); - drm_output_fini_crtc(output); - assert(!output->state_last); drm_output_state_free(output->state_cur); @@ -5148,12 +5171,6 @@ create_output_for_connector(struct drm_backend *b, output->destroy_pending = 0; output->disable_pending = 0; - if (drm_output_init_crtc(output, resources, connector) < 0) - goto err_output; - - if (drm_output_init_gamma_size(output) < 0) - goto err_output; - output->state_cur = drm_output_state_alloc(output, NULL); for (i = 0; i < head->connector->count_modes; i++) {