diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index fe59bf52..f2d99b97 100644 --- a/libweston/compositor-drm.c +++ b/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