[PATCH 1/4] drm: Add support for CRTC primary planes
Matt Roper
matthew.d.roper at intel.com
Thu Feb 27 14:14:40 PST 2014
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 at intel.com>
---
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
More information about the dri-devel
mailing list