diff options
author | Pekka Paalanen <pekka.paalanen@collabora.co.uk> | 2016-11-15 22:07:49 +0000 |
---|---|---|
committer | Daniel Stone <daniels@collabora.com> | 2017-02-07 19:16:32 +0000 |
commit | f1676789e9bb10d0b663f2d90015090ff3e3d733 (patch) | |
tree | ed1caab8ad258ebce142706ff3d538fd8d1b527f | |
parent | a8c15b17989f0b663eff3f214fc19ccef268688d (diff) |
compositor-drm: Discover atomic properties
Set the atomic client cap, where it exists, and use this to discover the
plane/CRTC/connector properties we require for atomic modesetting.
Differential Revision: https://phabricator.freedesktop.org/D1503
Signed-off-by: Daniel Stone <daniels@collabora.com>
Co-authored-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | libweston/compositor-drm.c | 143 |
2 files changed, 146 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index 7a6bb271..be3d7dbe 100644 --- a/configure.ac +++ b/configure.ac @@ -206,6 +206,9 @@ AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test x$enable_drm_compositor = xyes) if test x$enable_drm_compositor = xyes; then AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor]) PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm mtdev >= 1.1.0]) + PKG_CHECK_MODULES(DRM_COMPOSITOR_ATOMIC, [libdrm >= 2.4.62], + [AC_DEFINE([HAVE_DRM_ATOMIC], 1, [libdrm supports atomic API])], + [AC_MSG_WARN([libdrm does not support atomic modesetting, will omit that capability])]) PKG_CHECK_MODULES(DRM_COMPOSITOR_GBM, [gbm >= 10.2], [AC_DEFINE([HAVE_GBM_FD_IMPORT], 1, [gbm supports dmabuf import])], [AC_MSG_WARN([gbm does not support dmabuf import, will omit that capability])]) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 89848bb6..bff4ca50 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -100,6 +100,16 @@ struct property_item { */ enum wdrm_plane_property { WDRM_PLANE_TYPE = 0, + WDRM_PLANE_SRC_X, + WDRM_PLANE_SRC_Y, + WDRM_PLANE_SRC_W, + WDRM_PLANE_SRC_H, + WDRM_PLANE_CRTC_X, + WDRM_PLANE_CRTC_Y, + WDRM_PLANE_CRTC_W, + WDRM_PLANE_CRTC_H, + WDRM_PLANE_FB_ID, + WDRM_PLANE_CRTC_ID, WDRM_PLANE__COUNT }; @@ -123,6 +133,37 @@ struct plane_properties { }; /** + * List of properties attached to DRM CRTCs + */ +enum wdrm_crtc_property { + WDRM_CRTC_MODE_ID = 0, + WDRM_CRTC_ACTIVE, + WDRM_CRTC__COUNT +}; + +/** + * List of properties attached to DRM connectors + */ +enum wdrm_connector_property { + WDRM_CONNECTOR_CRTC_ID = 0, + WDRM_CONNECTOR__COUNT +}; + +/** + * Holding structure for CRTC properties. + */ +struct crtc_properties { + struct property_item item[WDRM_CRTC__COUNT]; +}; + +/** + * Holding structure for CRTC properties. + */ +struct connector_properties { + struct property_item item[WDRM_CONNECTOR__COUNT]; +}; + +/** * Mode for drm_output_state_duplicate. */ enum drm_output_state_duplicate_mode { @@ -171,6 +212,7 @@ struct drm_backend { int cursors_are_broken; bool universal_planes; + bool atomic_modeset; int use_pixman; @@ -300,6 +342,9 @@ struct drm_output { drmModePropertyPtr dpms_prop; uint32_t gbm_format; + struct crtc_properties props_crtc; + struct connector_properties props_conn; + int vblank_pending; int page_flip_pending; int destroy_pending; @@ -590,6 +635,16 @@ plane_properties_init(struct drm_plane *plane) { static const char * const plane_property_names[] = { [WDRM_PLANE_TYPE] = "type", + [WDRM_PLANE_SRC_X] = "SRC_X", + [WDRM_PLANE_SRC_Y] = "SRC_Y", + [WDRM_PLANE_SRC_W] = "SRC_W", + [WDRM_PLANE_SRC_H] = "SRC_H", + [WDRM_PLANE_CRTC_X] = "CRTC_X", + [WDRM_PLANE_CRTC_Y] = "CRTC_Y", + [WDRM_PLANE_CRTC_W] = "CRTC_W", + [WDRM_PLANE_CRTC_H] = "CRTC_H", + [WDRM_PLANE_FB_ID] = "FB_ID", + [WDRM_PLANE_CRTC_ID] = "CRTC_ID", }; static const char * const plane_type_names[] = { [WDRM_PLANE_TYPE_PRIMARY] = "Primary", @@ -682,6 +737,84 @@ drm_plane_get_type(struct drm_plane *plane) return WDRM_PLANE_TYPE_OVERLAY; } +/** + * Initialise DRM properties for CRTC and connector + * + * Set up the holding structures to track DRM object properties set on the CRTC + * and connector associated with an output. + * Free the memory allocated here with output_properties_release. + * + * @param b DRM backend + * @param output Output to configure + */ +static bool output_properties_init(struct drm_backend *b, + struct drm_output *output) +{ + static const char * const crtc_property_names[] = { + [WDRM_CRTC_MODE_ID] = "MODE_ID", + [WDRM_CRTC_ACTIVE] = "ACTIVE", + }; + static const char * const connector_property_names[] = { + [WDRM_CONNECTOR_CRTC_ID] = "CRTC_ID", + }; + uint32_t valid_mask, required_mask; + + static_assert(ARRAY_LENGTH(crtc_property_names) == WDRM_CRTC__COUNT, + "crtc_property_names mismatch with the enum"); + static_assert(WDRM_CRTC__COUNT <= 32, + "need more bits for crtc item_valid_mask"); + + static_assert(ARRAY_LENGTH(connector_property_names) == WDRM_CONNECTOR__COUNT, + "connector_property_names mismatch with the enum"); + static_assert(WDRM_CONNECTOR__COUNT <= 32, + "need more bits for connector item_valid_mask"); + + valid_mask = drm_properties_get_from_obj(b, + output->props_crtc.item, + crtc_property_names, + WDRM_CRTC__COUNT, + output->crtc_id, + DRM_MODE_OBJECT_CRTC); + + required_mask = 0; + if ((valid_mask & required_mask) != required_mask) { + weston_log("DRM error: failed to look up all CRTC properties " + "(wanted 0x%x got 0x%x) on ID %d\n", + required_mask, valid_mask, output->crtc_id); + return false; + } + + valid_mask = drm_properties_get_from_obj(b, + output->props_conn.item, + connector_property_names, + WDRM_CONNECTOR__COUNT, + output->connector_id, + DRM_MODE_OBJECT_CONNECTOR); + required_mask = 0; + if ((valid_mask & required_mask) != required_mask) { + weston_log("DRM error: failed to look up all connector properties " + "(wanted 0x%x got 0x%x) on ID %d\n", + required_mask, valid_mask, output->connector_id); + return false; + } + + return true; +} + +/** + * Free DRM CRTC and connector properties + * + * The counterpart to output_properties_init. + * + * @param output Output to release properties for + */ +static void output_properties_release(struct drm_output *output) +{ + property_item_array_release(output->props_crtc.item, WDRM_CRTC__COUNT); + property_item_array_release(output->props_conn.item, + WDRM_CONNECTOR__COUNT); +} + static void drm_output_set_cursor(struct drm_output_state *output_state); @@ -2552,6 +2685,13 @@ init_kms_caps(struct drm_backend *b) weston_log("DRM: %s universal planes\n", b->universal_planes ? "supports" : "does not support"); +#ifdef HAVE_DRM_ATOMIC + ret = drmSetClientCap(b->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1); + b->atomic_modeset = (ret == 0); +#endif + weston_log("DRM: %s atomic modesetting\n", + b->atomic_modeset ? "supports" : "does not support"); + return 0; } @@ -3816,6 +3956,7 @@ drm_output_destroy(struct weston_output *base) assert(!output->state_last); drm_output_state_free(output->state_cur); + output_properties_release(output); assert(!output->state_pending); free(output); @@ -3899,6 +4040,8 @@ create_output_for_connector(struct drm_backend *b, output->base.name = make_connector_name(connector); output->base.gamma_size = origcrtc->gamma_size; + output_properties_init(b, output); + output->destroy_pending = 0; output->disable_pending = 0; |