[PATCH weston v12 15/40] compositor-drm: Atomic modesetting support

Pekka Paalanen ppaalanen at gmail.com
Wed Oct 4 11:34:55 UTC 2017


On Tue, 26 Sep 2017 18:15:48 +0100
Daniel Stone <daniels at collabora.com> wrote:

> Add support for using the atomic-modesetting API to apply output state.
> Unlike previous series, this commit does not unflip sprites_are_broken,
> until further work has been done with assign_planes to make it reliable.
> 
> Signed-off-by: Daniel Stone <daniels at collabora.com>
> Co-authored-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
> Co-authored-by: Louis-Francis Ratté-Boulianne <louis-francis.ratte-boulianne at collabora.com>
> Co-authored-by: Derek Foreman <derek.foreman at collabora.co.uk>
> ---
>  configure.ac               |   2 +-
>  libweston/compositor-drm.c | 507 ++++++++++++++++++++++++++++++++++++++-------
>  2 files changed, 434 insertions(+), 75 deletions(-)

Hi Daniel!


> +#ifdef HAVE_DRM_ATOMIC
> +static int
> +crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output,
> +	      enum wdrm_crtc_property prop, uint64_t val)
> +{
> +	struct drm_property_info *info = &output->props_crtc[prop];
> +	int ret;
> +
> +	if (!info)
> +		return -1;

Should not this and the two functions below check that the prop_id was
actually found?

What happens if one uses property ID 0?

> +
> +	ret = drmModeAtomicAddProperty(req, output->crtc_id, info->prop_id,
> +				       val);
> +	return (ret <= 0) ? -1 : 0;
> +}
> +
> +static int
> +connector_add_prop(drmModeAtomicReq *req, struct drm_output *output,
> +		   enum wdrm_connector_property prop, uint64_t val)
> +{
> +	struct drm_property_info *info = &output->props_conn[prop];
> +	int ret;
> +
> +	if (!info)
> +		return -1;
> +
> +	ret = drmModeAtomicAddProperty(req, output->connector_id,
> +				       info->prop_id, val);
> +	return (ret <= 0) ? -1 : 0;
> +}
> +
> +static int
> +plane_add_prop(drmModeAtomicReq *req, struct drm_plane *plane,
> +	       enum wdrm_plane_property prop, uint64_t val)
> +{
> +	struct drm_property_info *info = &plane->props[prop];
> +	int ret;
> +
> +	if (!info)
> +		return -1;
> +
> +	ret = drmModeAtomicAddProperty(req, plane->plane_id, info->prop_id,
> +				       val);
> +	return (ret <= 0) ? -1 : 0;
> +}


> +static int
> +drm_pending_state_apply_atomic(struct drm_pending_state *pending_state)
> +{
> +	struct drm_backend *b = pending_state->backend;
> +	struct drm_output_state *output_state, *tmp;
> +	drmModeAtomicReq *req = drmModeAtomicAlloc();
> +	uint32_t flags = 0;
> +	int ret = 0;
> +
> +	if (!req)
> +		return -1;
> +
> +	if (b->state_invalid) {
> +		uint32_t *unused;
> +		int err;
> +
> +		/* If we need to reset all our state (e.g. because we've
> +		 * just started, or just been VT-switched in), explicitly
> +		 * disable all the CRTCs and connectors we aren't using. */
> +		wl_array_for_each(unused, &b->unused_connectors) {
> +			struct drm_property_info infos[WDRM_CONNECTOR__COUNT];
> +			struct drm_property_info *info;
> +			drmModeObjectProperties *props;
> +
> +			memset(infos, 0, sizeof(infos));

memset would be easier done with
	struct drm_property_info infos[WDRM_CONNECTOR__COUNT] = {};

> +
> +			props = drmModeObjectGetProperties(b->drm.fd,
> +							   *unused,
> +							   DRM_MODE_OBJECT_CONNECTOR);
> +			if (!props) {
> +				ret = -1;
> +				continue;
> +			}
> +
> +			drm_property_info_populate(b, connector_props, infos,
> +						   WDRM_CONNECTOR__COUNT,
> +						   props);
> +			drmModeFreeObjectProperties(props);
> +
> +			info = &infos[WDRM_CONNECTOR_CRTC_ID];
> +			err = drmModeAtomicAddProperty(req, *unused,
> +						       info->prop_id, 0);
> +			if (err <= 0)
> +				ret = -1;
> +
> +			info = &infos[WDRM_CONNECTOR_DPMS];
> +			if (info->prop_id > 0)
> +				err = drmModeAtomicAddProperty(req, *unused,
> +							       info->prop_id,
> +							       DRM_MODE_DPMS_OFF);
> +			if (err <= 0)
> +				ret = -1;
> +
> +			drm_property_info_free(infos, WDRM_CONNECTOR__COUNT);
> +		}
> +
> +		wl_array_for_each(unused, &b->unused_crtcs) {
> +			struct drm_property_info infos[WDRM_CRTC__COUNT];
> +			struct drm_property_info *info;
> +			drmModeObjectProperties *props;
> +			uint64_t active;
> +
> +			memset(infos, 0, sizeof(infos));
> +
> +			/* We can't emit a disable on a CRTC that's already
> +			 * off, as the kernel will refuse to generate an event
> +			 * for an off->off state and fail the commit.
> +			 */
> +			props = drmModeObjectGetProperties(b->drm.fd,
> +							   *unused,
> +							   DRM_MODE_OBJECT_CRTC);
> +			if (!props) {
> +				ret = -1;
> +				continue;
> +			}
> +
> +			drm_property_info_populate(b, crtc_props, infos,
> +						   WDRM_CRTC__COUNT,
> +						   props);
> +
> +			info = &infos[WDRM_CRTC_ACTIVE];
> +			active = drm_property_get_value(info, props, 0);
> +			drmModeFreeObjectProperties(props);
> +			if (active == 0) {
> +				drm_property_info_free(infos, WDRM_CRTC__COUNT);
> +				continue;
> +			}
> +
> +			err = drmModeAtomicAddProperty(req, *unused,
> +						       info->prop_id, 0);
> +			if (err <= 0)
> +				ret = -1;
> +
> +			info = &infos[WDRM_CRTC_MODE_ID];
> +			err = drmModeAtomicAddProperty(req, *unused,
> +						       info->prop_id, 0);
> +			if (err <= 0)
> +				ret = -1;
> +
> +			drm_property_info_free(infos, WDRM_CRTC__COUNT);
> +		}
> +
> +#if 0
> +		wl_array_for_each(unused, &b->unused_planes) {

I don't think we would ever need a unused_planes array since we create
a drm_plane for them all, right?

Should just go through the list of drm_planes.

> +			struct drm_property_info infos[WDRM_PLANE__COUNT];
> +			struct drm_property_info *info;
> +			drmModeObjectProperties *props;
> +
> +			memset(infos, 0, sizeof(infos));
> +
> +			drm_property_info_populate(b, props_plane, infos,
> +						   WDRM_PLANE__COUNT, props);
> +			drmModeFreeObjectProperties(props);
> +
> +			info = &infos[WDRM_PLANE_CRTC_ID];
> +			err = drmModeAtomicAddProperty(req, *unused,
> +						       info->prop_id, 0);
> +			if (err <= 0)
> +				ret = -1;
> +
> +			info = &infos[WDRM_PLANE_FB_ID];
> +			err = drmModeAtomicAddProperty(req, *unused,
> +						       info->prop_id, 0);
> +			if (err <= 0)
> +				ret = -1;
> +
> +			drm_property_info_free(infos, WDRM_PLANE__COUNT);
> +		}
> +#endif
> +
> +		flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
> +	}
> +
> +	wl_list_for_each(output_state, &pending_state->output_list, link)
> +		ret |= drm_output_apply_state_atomic(output_state, req, &flags);
> +
> +	if (ret != 0) {
> +		weston_log("atomic: couldn't compile atomic state\n");
> +		goto out;
> +	}
> +
> +	flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
> +	ret = drmModeAtomicCommit(b->drm.fd, req, flags, b);
> +	if (ret != 0) {
> +		weston_log("atomic: couldn't commit new state: %m\n");
> +		goto out;
> +	}
> +
> +	wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
> +			      link) {
> +		drm_output_assign_state(output_state,
> +					DRM_OUTPUT_STATE_UPDATE_ASYNCHRONOUS);
> +	}
> +
> +	b->state_invalid = false;
> +
> +	assert(wl_list_empty(&pending_state->output_list));
> +
> +out:
> +	drmModeAtomicFree(req);

Missing drm_pending_state_free()?


> +	return ret;
> +}
> +#endif
> +
>  static int
>  drm_pending_state_apply(struct drm_pending_state *pending_state)
>  {

Otherwise looks good to me.


Thanks,
pq
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20171004/980f40a5/attachment.sig>


More information about the wayland-devel mailing list