compositor-drm: start migration to head-based output API

Hook up the libweston facing head-based output API by introducing struct
drm_head, but leave it as a fake so that members can be migrated in
pieces in follow-up patches.

The DRM backend continues to create an output for each connected
connector only, and during output creation it also creates a drm_head
for it. This allows it to pretend it supports the head-based output API
as long as there is only one head per output ever attached.

create_output callback is fake, it will only look up the existing
drm_output by the head name.

Clones are not yet supported, hence max is defined to 1.

This unfortunately introduces some temporary code that will be revomed
later, but seems to be necessary to avoid a single big patch.

v6:
- add missing drm_head_destroy() call

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Ian Ray <ian.ray@ge.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Acked-by: Derek Foreman <derekf@osg.samsung.com>
dev
Pekka Paalanen 7 years ago
parent c80e954123
commit c112f00bd1
  1. 135
      libweston/compositor-drm.c

@ -83,6 +83,8 @@
#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64 #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
#endif #endif
#define MAX_CLONED_CONNECTORS 1
/** /**
* Represents the values of an enum-type KMS property * Represents the values of an enum-type KMS property
*/ */
@ -400,6 +402,13 @@ struct drm_plane {
uint32_t formats[]; uint32_t formats[];
}; };
struct drm_head {
struct weston_head base;
struct drm_backend *backend;
struct drm_output *output; /* XXX: temporary */
};
struct drm_output { struct drm_output {
struct weston_output base; struct weston_output base;
drmModeConnector *connector; drmModeConnector *connector;
@ -475,6 +484,12 @@ wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
} }
} }
static inline struct drm_head *
to_drm_head(struct weston_head *base)
{
return container_of(base, struct drm_head, base);
}
static inline struct drm_output * static inline struct drm_output *
to_drm_output(struct weston_output *base) to_drm_output(struct weston_output *base)
{ {
@ -4393,6 +4408,16 @@ setup_output_seat_constraint(struct drm_backend *b,
} }
} }
static int
drm_output_attach_head(struct weston_output *output_base,
struct weston_head *head_base)
{
if (wl_list_length(&output_base->head_list) >= MAX_CLONED_CONNECTORS)
return -1;
return 0;
}
static int static int
parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format) parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format)
{ {
@ -4810,11 +4835,15 @@ drm_output_deinit(struct weston_output *base)
b->state_invalid = true; b->state_invalid = true;
} }
static void
drm_head_destroy(struct drm_head *head);
static void static void
drm_output_destroy(struct weston_output *base) drm_output_destroy(struct weston_output *base)
{ {
struct drm_output *output = to_drm_output(base); struct drm_output *output = to_drm_output(base);
struct drm_backend *b = to_drm_backend(base->compositor); struct drm_backend *b = to_drm_backend(base->compositor);
struct weston_head *head = weston_output_get_first_head(base);
if (output->page_flip_pending || output->vblank_pending || if (output->page_flip_pending || output->vblank_pending ||
output->atomic_complete_pending) { output->atomic_complete_pending) {
@ -4845,6 +4874,10 @@ drm_output_destroy(struct weston_output *base)
drm_output_state_free(output->state_cur); drm_output_state_free(output->state_cur);
free(output); free(output);
/* XXX: temporary */
if (head)
drm_head_destroy(to_drm_head(head));
} }
static int static int
@ -4868,6 +4901,19 @@ drm_output_disable(struct weston_output *base)
return 0; return 0;
} }
static struct weston_output *
drm_output_create(struct weston_compositor *compositor, const char *name)
{
struct drm_head *head;
/* XXX: Temporary until we can have heads without an output */
wl_list_for_each(head, &compositor->head_list, base.compositor_link)
if (strcmp(name, head->base.name) == 0)
return &head->output->base;
return NULL;
}
/** /**
* Update the list of unused connectors and CRTCs * Update the list of unused connectors and CRTCs
* *
@ -4913,6 +4959,71 @@ drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
} }
} }
/**
* Create a Weston head for a connector
*
* Given a DRM connector, create a matching drm_head structure and add it
* to Weston's head list.
*
* @param b Weston backend structure
* @param connector_id DRM connector ID for the head
* @param drm_device udev device pointer
* @returns The new head, or NULL on failure.
*/
static struct drm_head *
drm_head_create(struct drm_backend *backend, uint32_t connector_id,
struct udev_device *drm_device)
{
struct drm_head *head;
drmModeConnector *connector;
char *name;
head = zalloc(sizeof *head);
if (!head)
return NULL;
connector = drmModeGetConnector(backend->drm.fd, connector_id);
if (!connector)
goto err_alloc;
name = make_connector_name(connector);
if (!name)
goto err_alloc;
weston_head_init(&head->base, name);
free(name);
head->backend = backend;
/* Unknown connection status is assumed disconnected. */
weston_head_set_connection_status(&head->base,
connector->connection == DRM_MODE_CONNECTED);
weston_compositor_add_head(backend->compositor, &head->base);
drmModeFreeConnector(connector);
weston_log("DRM: found head '%s', connector %d %s.\n",
head->base.name, connector_id,
head->base.connected ? "connected" : "disconnected");
return head;
err_alloc:
if (connector)
drmModeFreeConnector(connector);
free(head);
return NULL;
}
static void
drm_head_destroy(struct drm_head *head)
{
weston_head_release(&head->base);
free(head);
}
/** /**
* Create a Weston output structure * Create a Weston output structure
* *
@ -4933,7 +5044,7 @@ create_output_for_connector(struct drm_backend *b,
struct udev_device *drm_device) struct udev_device *drm_device)
{ {
struct drm_output *output; struct drm_output *output;
struct weston_head *head; struct drm_head *head;
drmModeObjectPropertiesPtr props; drmModeObjectPropertiesPtr props;
struct drm_mode *drm_mode; struct drm_mode *drm_mode;
char *name; char *name;
@ -4956,9 +5067,16 @@ create_output_for_connector(struct drm_backend *b,
weston_output_init(&output->base, b->compositor, name); weston_output_init(&output->base, b->compositor, name);
free(name); free(name);
/* XXX: temporary */
head = drm_head_create(b, connector->connector_id, drm_device);
if (!head)
abort();
head->output = output;
output->base.enable = drm_output_enable; output->base.enable = drm_output_enable;
output->base.destroy = drm_output_destroy; output->base.destroy = drm_output_destroy;
output->base.disable = drm_output_disable; output->base.disable = drm_output_disable;
output->base.attach_head = drm_output_attach_head;
output->destroy_pending = 0; output->destroy_pending = 0;
output->disable_pending = 0; output->disable_pending = 0;
@ -4974,23 +5092,22 @@ create_output_for_connector(struct drm_backend *b,
} }
drm_property_info_populate(b, connector_props, output->props_conn, drm_property_info_populate(b, connector_props, output->props_conn,
WDRM_CONNECTOR__COUNT, props); WDRM_CONNECTOR__COUNT, props);
head = &output->base.head;
find_and_parse_output_edid(b, output, props, find_and_parse_output_edid(b, output, props,
&make, &model, &serial_number); &make, &model, &serial_number);
weston_head_set_monitor_strings(head, make, model, serial_number); weston_head_set_monitor_strings(&head->base, make, model, serial_number);
weston_head_set_subpixel(head, weston_head_set_subpixel(&head->base,
drm_subpixel_to_wayland(output->connector->subpixel)); drm_subpixel_to_wayland(output->connector->subpixel));
drmModeFreeObjectProperties(props); drmModeFreeObjectProperties(props);
if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS || if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
output->connector->connector_type == DRM_MODE_CONNECTOR_eDP) output->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
weston_head_set_internal(head); weston_head_set_internal(&head->base);
if (drm_output_init_gamma_size(output) < 0) if (drm_output_init_gamma_size(output) < 0)
goto err_output; goto err_output;
weston_head_set_physical_size(head, output->connector->mmWidth, weston_head_set_physical_size(&head->base, output->connector->mmWidth,
output->connector->mmHeight); output->connector->mmHeight);
output->state_cur = drm_output_state_alloc(output, NULL); output->state_cur = drm_output_state_alloc(output, NULL);
@ -5008,6 +5125,7 @@ create_output_for_connector(struct drm_backend *b,
return 0; return 0;
err_output: err_output:
drm_head_destroy(head);
drm_output_destroy(&output->base); drm_output_destroy(&output->base);
return -1; return -1;
/* no fallthrough! */ /* no fallthrough! */
@ -5189,6 +5307,7 @@ static void
drm_destroy(struct weston_compositor *ec) drm_destroy(struct weston_compositor *ec)
{ {
struct drm_backend *b = to_drm_backend(ec); struct drm_backend *b = to_drm_backend(ec);
struct weston_head *base, *next;
udev_input_destroy(&b->input); udev_input_destroy(&b->input);
@ -5201,6 +5320,9 @@ drm_destroy(struct weston_compositor *ec)
weston_compositor_shutdown(ec); weston_compositor_shutdown(ec);
wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
drm_head_destroy(to_drm_head(base));
if (b->gbm) if (b->gbm)
gbm_device_destroy(b->gbm); gbm_device_destroy(b->gbm);
@ -5718,6 +5840,7 @@ drm_backend_create(struct weston_compositor *compositor,
b->base.repaint_begin = drm_repaint_begin; b->base.repaint_begin = drm_repaint_begin;
b->base.repaint_flush = drm_repaint_flush; b->base.repaint_flush = drm_repaint_flush;
b->base.repaint_cancel = drm_repaint_cancel; b->base.repaint_cancel = drm_repaint_cancel;
b->base.create_output = drm_output_create;
weston_setup_vt_switch_bindings(compositor); weston_setup_vt_switch_bindings(compositor);

Loading…
Cancel
Save