Allow drivers to provide a drm_plane structure corresponding to a CRTC's primary plane. These planes will be included in the plane list for any clients setting the DRM_CLIENT_CAP_EXPOSE_PRIMARY_PLANES capability bit. Signed-off-by: Matt Roper <matthew.d.roper@xxxxxxxxx> --- drivers/gpu/drm/drm_crtc.c | 168 ++++++++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/drm_ioctl.c | 5 ++ include/drm/drmP.h | 2 + include/drm/drm_crtc.h | 11 +++ include/uapi/drm/drm.h | 8 +++ 5 files changed, 189 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 35ea15d..21c6d4b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -274,6 +274,74 @@ const char *drm_get_connector_status_name(enum drm_connector_status status) } EXPORT_SYMBOL(drm_get_connector_status_name); +/* + * Default set of pixel formats supported by primary planes. This matches the + * set of formats accepted by the traditional modesetting interfaces; drivers + * need only provide their own format list if it differs from the default. + */ +static const uint32_t default_primary_plane_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_RGB332, + DRM_FORMAT_BGR233, + DRM_FORMAT_XRGB4444, + DRM_FORMAT_XBGR4444, + DRM_FORMAT_RGBX4444, + DRM_FORMAT_BGRX4444, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ABGR4444, + DRM_FORMAT_RGBA4444, + DRM_FORMAT_BGRA4444, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_RGBX5551, + DRM_FORMAT_BGRX5551, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_BGRA5551, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_RGBX1010102, + DRM_FORMAT_BGRX1010102, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_BGRA1010102, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_AYUV, + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, + DRM_FORMAT_NV61, + DRM_FORMAT_NV24, + DRM_FORMAT_NV42, + DRM_FORMAT_YUV410, + DRM_FORMAT_YVU410, + DRM_FORMAT_YUV411, + DRM_FORMAT_YVU411, + DRM_FORMAT_YUV420, + DRM_FORMAT_YVU420, + DRM_FORMAT_YUV422, + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, +}; + /** * drm_get_subpixel_order_name - return a string for a given subpixel enum * @order: enum of subpixel_order @@ -921,7 +989,7 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) EXPORT_SYMBOL(drm_encoder_cleanup); /** - * drm_plane_init - Initialise a new plane object + * drm_plane_init - Initialise a new sprite plane object * @dev: DRM device * @plane: plane object to init * @possible_crtcs: bitmask of possible CRTCs @@ -930,7 +998,9 @@ EXPORT_SYMBOL(drm_encoder_cleanup); * @format_count: number of elements in @formats * @priv: plane is private (hidden from userspace)? * - * Inits a new object created as base part of a driver plane object. + * Inits a new object created as base part of a driver plane object. This + * function should only be called for traditional sprite/overlay planes. + * Primary planes should be initialized via @drm_plane_set_primary. * * RETURNS: * Zero on success, error code on failure. @@ -984,6 +1054,74 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, EXPORT_SYMBOL(drm_plane_init); /** + * drm_plane_set_primary - Supply a primary plane for a CRTC + * @dev DRM device + * @plane: plane object representing the primary plane + * @crtc: CRTC this plane is associated with + * @funcs: callbacks for the new plane + * @formats: array of supported formats (%DRM_FORMAT_*). If NULL, the + * default list of formats traditionally supported by modesetting + * API's will be used and @format_count will be ignored. + * @format_count: number of elements in @formats + * + * Provides a drm_plane representing a CRTC's primary plane. This plane will + * only be exposed to clients that set the DRM_CLIENT_CAP_EXPOSE_PRIMARY_PLANES + * capability bit. + * + * RETURNS: + * Zero on success, error code on failure. + */ +int drm_plane_set_primary(struct drm_device *dev, struct drm_plane *plane, + struct drm_crtc *crtc, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, uint32_t format_count) +{ + int ret; + + drm_modeset_lock_all(dev); + + ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); + if (ret) + goto out; + + if (formats == NULL) { + formats = default_primary_plane_formats; + format_count = ARRAY_SIZE(default_primary_plane_formats); + } + + plane->base.properties = &plane->properties; + plane->dev = dev; + plane->funcs = funcs; + plane->format_types = kmalloc(sizeof(uint32_t) * format_count, + GFP_KERNEL); + if (!plane->format_types) { + DRM_DEBUG_KMS("out of memory when setting up primary plane\n"); + drm_mode_object_put(dev, &plane->base); + ret = -ENOMEM; + goto out; + } + + memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); + plane->format_count = format_count; + plane->possible_crtcs = drm_crtc_mask(crtc); + + /* + * Primary planes are not added to the general plane list, only linked + * to their CRTC. They will only be advertised to userspace clients + * that indicate support. + */ + crtc->primary_plane = plane; + dev->mode_config.num_primary_plane++; + INIT_LIST_HEAD(&plane->head); + + out: + drm_modeset_unlock_all(dev); + + return ret; +} +EXPORT_SYMBOL(drm_plane_set_primary); + +/** * drm_plane_cleanup - Clean up the core plane usage * @plane: plane to cleanup * @@ -1836,8 +1974,10 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, struct drm_mode_get_plane_res *plane_resp = data; struct drm_mode_config *config; struct drm_plane *plane; + struct drm_crtc *crtc; uint32_t __user *plane_ptr; int copied = 0, ret = 0; + unsigned num_planes; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -1845,14 +1985,32 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, drm_modeset_lock_all(dev); config = &dev->mode_config; + num_planes = config->num_plane; + if (file_priv->expose_primary_planes) + num_planes += config->num_primary_plane; + /* * This ioctl is called twice, once to determine how much space is * needed, and the 2nd time to fill it. */ - if (config->num_plane && - (plane_resp->count_planes >= config->num_plane)) { + if (num_planes && + (plane_resp->count_planes >= num_planes)) { plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; + if (file_priv->expose_primary_planes) { + list_for_each_entry(crtc, &config->crtc_list, head) { + if (!crtc->primary_plane) + continue; + + if (put_user(crtc->primary_plane->base.id, + plane_ptr + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + list_for_each_entry(plane, &config->plane_list, head) { if (put_user(plane->base.id, plane_ptr + copied)) { ret = -EFAULT; @@ -1861,7 +2019,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, copied++; } } - plane_resp->count_planes = config->num_plane; + plane_resp->count_planes = num_planes; out: drm_modeset_unlock_all(dev); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index dffc836..03579d6 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -316,6 +316,11 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; file_priv->stereo_allowed = req->value; break; + case DRM_CLIENT_CAP_EXPOSE_PRIMARY_PLANES: + if (req->value > 1) + return -EINVAL; + file_priv->expose_primary_planes = req->value; + break; default: return -EINVAL; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 04a7f31..997fa29 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -437,6 +437,8 @@ struct drm_file { unsigned is_master :1; /* this file private is a master for a minor */ /* true when the client has asked us to expose stereo 3D mode flags */ unsigned stereo_allowed :1; + /* true if client understands CRTC primary planes in the plane list */ + unsigned expose_primary_planes:1; struct pid *pid; kuid_t uid; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index ce9ee60..33a955b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -429,6 +429,11 @@ struct drm_crtc { * by drm_mode_set_config_internal to implement correct refcounting. */ struct drm_framebuffer *old_fb; + /* Primary plane to expose to userspace if the client sets the 'expose + * primary planes' cap. + */ + struct drm_plane *primary_plane; + bool enabled; /* Requested mode from modesetting. */ @@ -859,6 +864,7 @@ struct drm_mode_config { int num_plane; struct list_head plane_list; + int num_primary_plane; int num_crtc; struct list_head crtc_list; @@ -984,6 +990,11 @@ extern int drm_plane_init(struct drm_device *dev, const struct drm_plane_funcs *funcs, const uint32_t *formats, uint32_t format_count, bool priv); +extern int drm_plane_set_primary(struct drm_device *dev, + struct drm_plane *plane, struct drm_crtc *crtc, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, + uint32_t format_count); extern void drm_plane_cleanup(struct drm_plane *plane); extern void drm_plane_force_disable(struct drm_plane *plane); diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 3c9a833..58a2468 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -635,6 +635,14 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_STEREO_3D 1 +/** + * DRM_CLIENT_CAP_EXPOSE_PRIMARY_PLANES + * + * If set to 1, the DRM core will expose CRTC primary planes along with + * sprite/overlay planes. + */ +#define DRM_CLIENT_CAP_EXPOSE_PRIMARY_PLANES 2 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; -- 1.8.5.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel