compositor-drm: factor out drm_output_init_crtc()
Factor out drm_output_init_crtc() and drm_output_fini_crtc(), so that the call sites can later be moved easily. On fini, reset scanout_plane and cursor_plane to NULL, so that in the future when the drm_output is not longer destroyed immediately after, we free the planes for other use. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reviewed-by: Ian Ray <ian.ray@ge.com> [Pekka: set crtc_id/pipe at top, reset both on error] Reviewed-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
+106
-52
@@ -4593,6 +4593,109 @@ drm_output_init_gamma_size(struct drm_output *output)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Allocate a CRTC for the output
|
||||||
|
*
|
||||||
|
* @param output The output with no allocated CRTC.
|
||||||
|
* @param resources DRM KMS resources.
|
||||||
|
* @param connector The DRM KMS connector data.
|
||||||
|
* @return 0 on success, -1 on failure.
|
||||||
|
*
|
||||||
|
* Finds a free CRTC that can drive the given connector, reserves the CRTC
|
||||||
|
* for the output, and loads the CRTC properties.
|
||||||
|
*
|
||||||
|
* Populates the cursor and scanout planes.
|
||||||
|
*
|
||||||
|
* On failure, the output remains without a CRTC.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
drm_output_init_crtc(struct drm_output *output,
|
||||||
|
drmModeRes *resources, drmModeConnector *connector)
|
||||||
|
{
|
||||||
|
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
||||||
|
drmModeObjectPropertiesPtr props;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(output->crtc_id == 0);
|
||||||
|
|
||||||
|
i = find_crtc_for_connector(b, resources, connector);
|
||||||
|
if (i < 0) {
|
||||||
|
weston_log("No usable crtc/encoder pair for connector.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->crtc_id = resources->crtcs[i];
|
||||||
|
output->pipe = i;
|
||||||
|
|
||||||
|
props = drmModeObjectGetProperties(b->drm.fd, output->crtc_id,
|
||||||
|
DRM_MODE_OBJECT_CRTC);
|
||||||
|
if (!props) {
|
||||||
|
weston_log("failed to get CRTC properties\n");
|
||||||
|
goto err_crtc;
|
||||||
|
}
|
||||||
|
drm_property_info_populate(b, crtc_props, output->props_crtc,
|
||||||
|
WDRM_CRTC__COUNT, props);
|
||||||
|
drmModeFreeObjectProperties(props);
|
||||||
|
|
||||||
|
output->scanout_plane =
|
||||||
|
drm_output_find_special_plane(b, output,
|
||||||
|
WDRM_PLANE_TYPE_PRIMARY);
|
||||||
|
if (!output->scanout_plane) {
|
||||||
|
weston_log("Failed to find primary plane for output %s\n",
|
||||||
|
output->base.name);
|
||||||
|
goto err_crtc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failing to find a cursor plane is not fatal, as we'll fall back
|
||||||
|
* to software cursor. */
|
||||||
|
output->cursor_plane =
|
||||||
|
drm_output_find_special_plane(b, output,
|
||||||
|
WDRM_PLANE_TYPE_CURSOR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_crtc:
|
||||||
|
output->crtc_id = 0;
|
||||||
|
output->pipe = 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Free the CRTC from the output
|
||||||
|
*
|
||||||
|
* @param output The output whose CRTC to deallocate.
|
||||||
|
*
|
||||||
|
* The CRTC reserved for the given output becomes free to use again.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
drm_output_fini_crtc(struct drm_output *output)
|
||||||
|
{
|
||||||
|
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
||||||
|
|
||||||
|
if (!b->universal_planes && !b->shutting_down) {
|
||||||
|
/* With universal planes, the 'special' planes are allocated at
|
||||||
|
* startup, freed at shutdown, and live on the plane list in
|
||||||
|
* between. We want the planes to continue to exist and be freed
|
||||||
|
* up for other outputs.
|
||||||
|
*
|
||||||
|
* Without universal planes, our special planes are
|
||||||
|
* pseudo-planes allocated at output creation, freed at output
|
||||||
|
* destruction, and not usable by other outputs.
|
||||||
|
*
|
||||||
|
* On the other hand, if the compositor is already shutting down,
|
||||||
|
* the plane has already been destroyed.
|
||||||
|
*/
|
||||||
|
if (output->cursor_plane)
|
||||||
|
drm_plane_destroy(output->cursor_plane);
|
||||||
|
if (output->scanout_plane)
|
||||||
|
drm_plane_destroy(output->scanout_plane);
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_property_info_free(output->props_crtc, WDRM_CRTC__COUNT);
|
||||||
|
output->crtc_id = 0;
|
||||||
|
output->cursor_plane = NULL;
|
||||||
|
output->scanout_plane = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
drm_output_enable(struct weston_output *base)
|
drm_output_enable(struct weston_output *base)
|
||||||
{
|
{
|
||||||
@@ -4715,25 +4818,6 @@ drm_output_destroy(struct weston_output *base)
|
|||||||
if (output->base.enabled)
|
if (output->base.enabled)
|
||||||
drm_output_deinit(&output->base);
|
drm_output_deinit(&output->base);
|
||||||
|
|
||||||
if (!b->universal_planes && !b->shutting_down) {
|
|
||||||
/* With universal planes, the 'special' planes are allocated at
|
|
||||||
* startup, freed at shutdown, and live on the plane list in
|
|
||||||
* between. We want the planes to continue to exist and be freed
|
|
||||||
* up for other outputs.
|
|
||||||
*
|
|
||||||
* Without universal planes, our special planes are
|
|
||||||
* pseudo-planes allocated at output creation, freed at output
|
|
||||||
* destruction, and not usable by other outputs.
|
|
||||||
*
|
|
||||||
* On the other hand, if the compositor is already shutting down,
|
|
||||||
* the plane has already been destroyed.
|
|
||||||
*/
|
|
||||||
if (output->cursor_plane)
|
|
||||||
drm_plane_destroy(output->cursor_plane);
|
|
||||||
if (output->scanout_plane)
|
|
||||||
drm_plane_destroy(output->scanout_plane);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
|
wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
|
||||||
base.link)
|
base.link)
|
||||||
drm_output_destroy_mode(b, drm_mode);
|
drm_output_destroy_mode(b, drm_mode);
|
||||||
@@ -4743,9 +4827,9 @@ drm_output_destroy(struct weston_output *base)
|
|||||||
|
|
||||||
weston_output_release(&output->base);
|
weston_output_release(&output->base);
|
||||||
|
|
||||||
drm_property_info_free(output->props_conn, WDRM_CONNECTOR__COUNT);
|
drm_output_fini_crtc(output);
|
||||||
drm_property_info_free(output->props_crtc, WDRM_CRTC__COUNT);
|
|
||||||
|
|
||||||
|
drm_property_info_free(output->props_conn, WDRM_CONNECTOR__COUNT);
|
||||||
drmModeFreeConnector(output->connector);
|
drmModeFreeConnector(output->connector);
|
||||||
|
|
||||||
if (output->backlight)
|
if (output->backlight)
|
||||||
@@ -4851,19 +4935,11 @@ create_output_for_connector(struct drm_backend *b,
|
|||||||
const char *serial_number = "unknown";
|
const char *serial_number = "unknown";
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = find_crtc_for_connector(b, resources, connector);
|
|
||||||
if (i < 0) {
|
|
||||||
weston_log("No usable crtc/encoder pair for connector.\n");
|
|
||||||
goto err_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
output = zalloc(sizeof *output);
|
output = zalloc(sizeof *output);
|
||||||
if (output == NULL)
|
if (output == NULL)
|
||||||
goto err_init;
|
goto err_init;
|
||||||
|
|
||||||
output->connector = connector;
|
output->connector = connector;
|
||||||
output->crtc_id = resources->crtcs[i];
|
|
||||||
output->pipe = i;
|
|
||||||
output->connector_id = connector->connector_id;
|
output->connector_id = connector->connector_id;
|
||||||
|
|
||||||
output->backlight = backlight_init(drm_device,
|
output->backlight = backlight_init(drm_device,
|
||||||
@@ -4880,15 +4956,8 @@ create_output_for_connector(struct drm_backend *b,
|
|||||||
output->destroy_pending = 0;
|
output->destroy_pending = 0;
|
||||||
output->disable_pending = 0;
|
output->disable_pending = 0;
|
||||||
|
|
||||||
props = drmModeObjectGetProperties(b->drm.fd, output->crtc_id,
|
if (drm_output_init_crtc(output, resources, connector) < 0)
|
||||||
DRM_MODE_OBJECT_CRTC);
|
|
||||||
if (!props) {
|
|
||||||
weston_log("failed to get CRTC properties\n");
|
|
||||||
goto err_output;
|
goto err_output;
|
||||||
}
|
|
||||||
drm_property_info_populate(b, crtc_props, output->props_crtc,
|
|
||||||
WDRM_CRTC__COUNT, props);
|
|
||||||
drmModeFreeObjectProperties(props);
|
|
||||||
|
|
||||||
props = drmModeObjectGetProperties(b->drm.fd, connector->connector_id,
|
props = drmModeObjectGetProperties(b->drm.fd, connector->connector_id,
|
||||||
DRM_MODE_OBJECT_CONNECTOR);
|
DRM_MODE_OBJECT_CONNECTOR);
|
||||||
@@ -4927,21 +4996,6 @@ create_output_for_connector(struct drm_backend *b,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output->scanout_plane =
|
|
||||||
drm_output_find_special_plane(b, output,
|
|
||||||
WDRM_PLANE_TYPE_PRIMARY);
|
|
||||||
if (!output->scanout_plane) {
|
|
||||||
weston_log("Failed to find primary plane for output %s\n",
|
|
||||||
output->base.name);
|
|
||||||
goto err_output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failing to find a cursor plane is not fatal, as we'll fall back
|
|
||||||
* to software cursor. */
|
|
||||||
output->cursor_plane =
|
|
||||||
drm_output_find_special_plane(b, output,
|
|
||||||
WDRM_PLANE_TYPE_CURSOR);
|
|
||||||
|
|
||||||
weston_compositor_add_pending_output(&output->base, b->compositor);
|
weston_compositor_add_pending_output(&output->base, b->compositor);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user