aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@vmware.com>2009-12-03 18:25:47 -0500
committerDave Airlie <airlied@redhat.com>2009-12-03 18:25:47 -0500
commit884840aa3ce3214259e69557be5b4ce0d781ffa4 (patch)
tree98dfd51c879df19428f3f6795fd32a8f2136ccb3 /drivers
parentc3a73ba13bac7fd96030f39202b2d37fb19c46a6 (diff)
drm: Add dirty ioctl and property
This commit adds a ioctl and property to allow userspace to notify the kernel that a framebuffer has changed. Instead of snooping the command stream this allows finer grained tracking of which areas have changed. The primary user for this functionality is virtual hardware like the vmware svga device, but also Xen hardware likes to be notify. There is also real hardware like DisplayLink and DisplayPort that might take advantage of this ioctl. Signed-off-by: Jakob Bornecrantz <jakob@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_crtc.c104
-rw-r--r--drivers/gpu/drm/drm_drv.c1
2 files changed, 105 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 32756e67dd5..4fe321dc900 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -125,6 +125,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
125DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, 125DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
126 drm_tv_subconnector_enum_list) 126 drm_tv_subconnector_enum_list)
127 127
128static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
129 { DRM_MODE_DIRTY_OFF, "Off" },
130 { DRM_MODE_DIRTY_ON, "On" },
131 { DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
132};
133
134DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
135 drm_dirty_info_enum_list)
136
128struct drm_conn_prop_enum_list { 137struct drm_conn_prop_enum_list {
129 int type; 138 int type;
130 char *name; 139 char *name;
@@ -802,6 +811,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev)
802EXPORT_SYMBOL(drm_mode_create_dithering_property); 811EXPORT_SYMBOL(drm_mode_create_dithering_property);
803 812
804/** 813/**
814 * drm_mode_create_dirty_property - create dirty property
815 * @dev: DRM device
816 *
817 * Called by a driver the first time it's needed, must be attached to desired
818 * connectors.
819 */
820int drm_mode_create_dirty_info_property(struct drm_device *dev)
821{
822 struct drm_property *dirty_info;
823 int i;
824
825 if (dev->mode_config.dirty_info_property)
826 return 0;
827
828 dirty_info =
829 drm_property_create(dev, DRM_MODE_PROP_ENUM |
830 DRM_MODE_PROP_IMMUTABLE,
831 "dirty",
832 ARRAY_SIZE(drm_dirty_info_enum_list));
833 for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++)
834 drm_property_add_enum(dirty_info, i,
835 drm_dirty_info_enum_list[i].type,
836 drm_dirty_info_enum_list[i].name);
837 dev->mode_config.dirty_info_property = dirty_info;
838
839 return 0;
840}
841EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
842
843/**
805 * drm_mode_config_init - initialize DRM mode_configuration structure 844 * drm_mode_config_init - initialize DRM mode_configuration structure
806 * @dev: DRM device 845 * @dev: DRM device
807 * 846 *
@@ -1753,6 +1792,71 @@ out:
1753 return ret; 1792 return ret;
1754} 1793}
1755 1794
1795int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
1796 void *data, struct drm_file *file_priv)
1797{
1798 struct drm_clip_rect __user *clips_ptr;
1799 struct drm_clip_rect *clips = NULL;
1800 struct drm_mode_fb_dirty_cmd *r = data;
1801 struct drm_mode_object *obj;
1802 struct drm_framebuffer *fb;
1803 unsigned flags;
1804 int num_clips;
1805 int ret = 0;
1806
1807 mutex_lock(&dev->mode_config.mutex);
1808 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
1809 if (!obj) {
1810 DRM_ERROR("invalid framebuffer id\n");
1811 ret = -EINVAL;
1812 goto out_err1;
1813 }
1814 fb = obj_to_fb(obj);
1815
1816 num_clips = r->num_clips;
1817 clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
1818
1819 if (!num_clips != !clips_ptr) {
1820 ret = -EINVAL;
1821 goto out_err1;
1822 }
1823
1824 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
1825
1826 /* If userspace annotates copy, clips must come in pairs */
1827 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
1828 ret = -EINVAL;
1829 goto out_err1;
1830 }
1831
1832 if (num_clips && clips_ptr) {
1833 clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
1834 if (!clips) {
1835 ret = -ENOMEM;
1836 goto out_err1;
1837 }
1838
1839 ret = copy_from_user(clips, clips_ptr,
1840 num_clips * sizeof(*clips));
1841 if (ret)
1842 goto out_err2;
1843 }
1844
1845 if (fb->funcs->dirty) {
1846 ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips);
1847 } else {
1848 ret = -ENOSYS;
1849 goto out_err2;
1850 }
1851
1852out_err2:
1853 kfree(clips);
1854out_err1:
1855 mutex_unlock(&dev->mode_config.mutex);
1856 return ret;
1857}
1858
1859
1756/** 1860/**
1757 * drm_fb_release - remove and free the FBs on this file 1861 * drm_fb_release - remove and free the FBs on this file
1758 * @filp: file * from the ioctl 1862 * @filp: file * from the ioctl
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index bfaf59b02bd..ff2f1042cb4 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -146,6 +146,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
146 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), 146 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
147 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), 147 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
148 DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 148 DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
149 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW)
149}; 150};
150 151
151#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) 152#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )