diff options
-rw-r--r-- | drivers/char/drm/drm.h | 24 | ||||
-rw-r--r-- | drivers/char/drm/drmP.h | 13 | ||||
-rw-r--r-- | drivers/char/drm/drm_drawable.c | 230 | ||||
-rw-r--r-- | drivers/char/drm/drm_drv.c | 2 | ||||
-rw-r--r-- | drivers/char/drm/drm_stub.c | 1 |
5 files changed, 262 insertions, 8 deletions
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index 077d0b1914ab..07a699029c3e 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h | |||
@@ -117,6 +117,14 @@ typedef struct drm_clip_rect { | |||
117 | } drm_clip_rect_t; | 117 | } drm_clip_rect_t; |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * Drawable information. | ||
121 | */ | ||
122 | typedef struct drm_drawable_info { | ||
123 | unsigned int num_rects; | ||
124 | drm_clip_rect_t *rects; | ||
125 | } drm_drawable_info_t; | ||
126 | |||
127 | /** | ||
120 | * Texture region, | 128 | * Texture region, |
121 | */ | 129 | */ |
122 | typedef struct drm_tex_region { | 130 | typedef struct drm_tex_region { |
@@ -444,6 +452,20 @@ typedef struct drm_draw { | |||
444 | } drm_draw_t; | 452 | } drm_draw_t; |
445 | 453 | ||
446 | /** | 454 | /** |
455 | * DRM_IOCTL_UPDATE_DRAW ioctl argument type. | ||
456 | */ | ||
457 | typedef enum { | ||
458 | DRM_DRAWABLE_CLIPRECTS, | ||
459 | } drm_drawable_info_type_t; | ||
460 | |||
461 | typedef struct drm_update_draw { | ||
462 | drm_drawable_t handle; | ||
463 | unsigned int type; | ||
464 | unsigned int num; | ||
465 | unsigned long long data; | ||
466 | } drm_update_draw_t; | ||
467 | |||
468 | /** | ||
447 | * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. | 469 | * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. |
448 | */ | 470 | */ |
449 | typedef struct drm_auth { | 471 | typedef struct drm_auth { |
@@ -625,6 +647,8 @@ typedef struct drm_set_version { | |||
625 | 647 | ||
626 | #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) | 648 | #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) |
627 | 649 | ||
650 | #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t) | ||
651 | |||
628 | /** | 652 | /** |
629 | * Device specific ioctls should only be in their respective headers | 653 | * Device specific ioctls should only be in their respective headers |
630 | * The device specific ioctl range is from 0x40 to 0x79. | 654 | * The device specific ioctl range is from 0x40 to 0x79. |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index d7135d41a42a..01e1f2528659 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -742,6 +742,15 @@ typedef struct drm_device { | |||
742 | drm_local_map_t *agp_buffer_map; | 742 | drm_local_map_t *agp_buffer_map; |
743 | unsigned int agp_buffer_token; | 743 | unsigned int agp_buffer_token; |
744 | drm_head_t primary; /**< primary screen head */ | 744 | drm_head_t primary; /**< primary screen head */ |
745 | |||
746 | /** \name Drawable information */ | ||
747 | /*@{ */ | ||
748 | spinlock_t drw_lock; | ||
749 | unsigned int drw_bitfield_length; | ||
750 | u32 *drw_bitfield; | ||
751 | unsigned int drw_info_length; | ||
752 | drm_drawable_info_t **drw_info; | ||
753 | /*@} */ | ||
745 | } drm_device_t; | 754 | } drm_device_t; |
746 | 755 | ||
747 | static __inline__ int drm_core_check_feature(struct drm_device *dev, | 756 | static __inline__ int drm_core_check_feature(struct drm_device *dev, |
@@ -889,6 +898,10 @@ extern int drm_adddraw(struct inode *inode, struct file *filp, | |||
889 | unsigned int cmd, unsigned long arg); | 898 | unsigned int cmd, unsigned long arg); |
890 | extern int drm_rmdraw(struct inode *inode, struct file *filp, | 899 | extern int drm_rmdraw(struct inode *inode, struct file *filp, |
891 | unsigned int cmd, unsigned long arg); | 900 | unsigned int cmd, unsigned long arg); |
901 | extern int drm_update_drawable_info(struct inode *inode, struct file *filp, | ||
902 | unsigned int cmd, unsigned long arg); | ||
903 | extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, | ||
904 | drm_drawable_t id); | ||
892 | 905 | ||
893 | /* Authentication IOCTL support (drm_auth.h) */ | 906 | /* Authentication IOCTL support (drm_auth.h) */ |
894 | extern int drm_getmagic(struct inode *inode, struct file *filp, | 907 | extern int drm_getmagic(struct inode *inode, struct file *filp, |
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c index 7857453c4f48..e5f97def26bf 100644 --- a/drivers/char/drm/drm_drawable.c +++ b/drivers/char/drm/drm_drawable.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * | 4 | * |
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | 5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
6 | * \author Gareth Hughes <gareth@valinux.com> | 6 | * \author Gareth Hughes <gareth@valinux.com> |
7 | * \author Michel Dänzer <michel@tungstengraphics.com> | ||
7 | */ | 8 | */ |
8 | 9 | ||
9 | /* | 10 | /* |
@@ -36,21 +37,234 @@ | |||
36 | #include "drmP.h" | 37 | #include "drmP.h" |
37 | 38 | ||
38 | /** No-op. */ | 39 | /** No-op. */ |
39 | int drm_adddraw(struct inode *inode, struct file *filp, | 40 | int drm_adddraw(DRM_IOCTL_ARGS) |
40 | unsigned int cmd, unsigned long arg) | ||
41 | { | 41 | { |
42 | DRM_DEVICE; | ||
43 | unsigned long irqflags; | ||
44 | int i, j = 0; | ||
42 | drm_draw_t draw; | 45 | drm_draw_t draw; |
43 | 46 | ||
44 | draw.handle = 0; /* NOOP */ | 47 | spin_lock_irqsave(&dev->drw_lock, irqflags); |
48 | |||
49 | for (i = 0; i < dev->drw_bitfield_length; i++) { | ||
50 | u32 bitfield = dev->drw_bitfield[i]; | ||
51 | |||
52 | if (bitfield == ~0) | ||
53 | continue; | ||
54 | |||
55 | for (; j < sizeof(bitfield); j++) | ||
56 | if (!(bitfield & (1 << j))) | ||
57 | goto done; | ||
58 | } | ||
59 | done: | ||
60 | |||
61 | if (i == dev->drw_bitfield_length) { | ||
62 | u32 *new_bitfield = drm_realloc(dev->drw_bitfield, i * 4, | ||
63 | (i + 1) * 4, DRM_MEM_BUFS); | ||
64 | |||
65 | if (!new_bitfield) { | ||
66 | DRM_ERROR("Failed to allocate new drawable bitfield\n"); | ||
67 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
68 | return DRM_ERR(ENOMEM); | ||
69 | } | ||
70 | |||
71 | if (32 * (i + 1) > dev->drw_info_length) { | ||
72 | void *new_info = drm_realloc(dev->drw_info, | ||
73 | dev->drw_info_length * | ||
74 | sizeof(drm_drawable_info_t*), | ||
75 | 32 * (i + 1) * | ||
76 | sizeof(drm_drawable_info_t*), | ||
77 | DRM_MEM_BUFS); | ||
78 | |||
79 | if (!new_info) { | ||
80 | DRM_ERROR("Failed to allocate new drawable info" | ||
81 | " array\n"); | ||
82 | |||
83 | drm_free(new_bitfield, (i + 1) * 4, DRM_MEM_BUFS); | ||
84 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
85 | return DRM_ERR(ENOMEM); | ||
86 | } | ||
87 | |||
88 | dev->drw_info = (drm_drawable_info_t**)new_info; | ||
89 | } | ||
90 | |||
91 | new_bitfield[i] = 0; | ||
92 | |||
93 | dev->drw_bitfield = new_bitfield; | ||
94 | dev->drw_bitfield_length++; | ||
95 | } | ||
96 | |||
97 | dev->drw_bitfield[i] |= 1 << j; | ||
98 | |||
99 | draw.handle = i * sizeof(u32) + j; | ||
45 | DRM_DEBUG("%d\n", draw.handle); | 100 | DRM_DEBUG("%d\n", draw.handle); |
46 | if (copy_to_user((drm_draw_t __user *) arg, &draw, sizeof(draw))) | 101 | |
47 | return -EFAULT; | 102 | dev->drw_info[draw.handle] = NULL; |
103 | |||
104 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
105 | |||
106 | DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw)); | ||
107 | |||
48 | return 0; | 108 | return 0; |
49 | } | 109 | } |
50 | 110 | ||
51 | /** No-op. */ | 111 | /** No-op. */ |
52 | int drm_rmdraw(struct inode *inode, struct file *filp, | 112 | int drm_rmdraw(DRM_IOCTL_ARGS) |
53 | unsigned int cmd, unsigned long arg) | ||
54 | { | 113 | { |
55 | return 0; /* NOOP */ | 114 | DRM_DEVICE; |
115 | drm_draw_t draw; | ||
116 | unsigned int idx, mod; | ||
117 | unsigned long irqflags; | ||
118 | |||
119 | DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data, | ||
120 | sizeof(draw)); | ||
121 | |||
122 | idx = draw.handle / 32; | ||
123 | mod = draw.handle % 32; | ||
124 | |||
125 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
126 | |||
127 | if (idx >= dev->drw_bitfield_length || | ||
128 | !(dev->drw_bitfield[idx] & (1 << mod))) { | ||
129 | DRM_DEBUG("No such drawable %d\n", draw.handle); | ||
130 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | dev->drw_bitfield[idx] &= ~(1 << mod); | ||
135 | |||
136 | if (idx == (dev->drw_bitfield_length - 1)) { | ||
137 | while (idx >= 0 && !dev->drw_bitfield[idx]) | ||
138 | --idx; | ||
139 | |||
140 | if (idx != draw.handle / 32) { | ||
141 | u32 *new_bitfield = drm_realloc(dev->drw_bitfield, | ||
142 | dev->drw_bitfield_length * 4, | ||
143 | (idx + 1) * 4, | ||
144 | DRM_MEM_BUFS); | ||
145 | |||
146 | if (new_bitfield || idx == -1) { | ||
147 | dev->drw_bitfield = new_bitfield; | ||
148 | dev->drw_bitfield_length = idx + 1; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | if (32 * dev->drw_bitfield_length < dev->drw_info_length) { | ||
154 | void *new_info = drm_realloc(dev->drw_info, | ||
155 | dev->drw_info_length * | ||
156 | sizeof(drm_drawable_info_t*), | ||
157 | 32 * dev->drw_bitfield_length * | ||
158 | sizeof(drm_drawable_info_t*), | ||
159 | DRM_MEM_BUFS); | ||
160 | |||
161 | if (new_info || !dev->drw_bitfield_length) { | ||
162 | dev->drw_info = (drm_drawable_info_t**)new_info; | ||
163 | dev->drw_info_length = 32 * dev->drw_bitfield_length; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
168 | |||
169 | DRM_DEBUG("%d\n", draw.handle); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | int drm_update_drawable_info(DRM_IOCTL_ARGS) { | ||
174 | DRM_DEVICE; | ||
175 | drm_update_draw_t update; | ||
176 | unsigned int id, idx, mod; | ||
177 | unsigned long irqflags; | ||
178 | drm_drawable_info_t *info; | ||
179 | void *new_data; | ||
180 | |||
181 | DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data, | ||
182 | sizeof(update)); | ||
183 | |||
184 | id = update.handle; | ||
185 | idx = id / 32; | ||
186 | mod = id % 32; | ||
187 | |||
188 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
189 | |||
190 | if (idx >= dev->drw_bitfield_length || | ||
191 | !(dev->drw_bitfield[idx] & (1 << mod))) { | ||
192 | DRM_ERROR("No such drawable %d\n", update.handle); | ||
193 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
194 | return DRM_ERR(EINVAL); | ||
195 | } | ||
196 | |||
197 | info = dev->drw_info[id]; | ||
198 | |||
199 | if (!info) { | ||
200 | info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS); | ||
201 | |||
202 | if (!info) { | ||
203 | DRM_ERROR("Failed to allocate drawable info memory\n"); | ||
204 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
205 | return DRM_ERR(ENOMEM); | ||
206 | } | ||
207 | |||
208 | dev->drw_info[id] = info; | ||
209 | } | ||
210 | |||
211 | switch (update.type) { | ||
212 | case DRM_DRAWABLE_CLIPRECTS: | ||
213 | if (update.num != info->num_rects) { | ||
214 | new_data = drm_alloc(update.num * | ||
215 | sizeof(drm_clip_rect_t), | ||
216 | DRM_MEM_BUFS); | ||
217 | |||
218 | if (!new_data) { | ||
219 | DRM_ERROR("Can't allocate cliprect memory\n"); | ||
220 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
221 | return DRM_ERR(ENOMEM); | ||
222 | } | ||
223 | |||
224 | info->rects = new_data; | ||
225 | } | ||
226 | |||
227 | if (DRM_COPY_FROM_USER(info->rects, | ||
228 | (drm_clip_rect_t __user *) | ||
229 | (unsigned long)update.data, | ||
230 | update.num * sizeof(drm_clip_rect_t))) { | ||
231 | DRM_ERROR("Can't copy cliprects from userspace\n"); | ||
232 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
233 | return DRM_ERR(EFAULT); | ||
234 | } | ||
235 | |||
236 | if (update.num != info->num_rects) { | ||
237 | drm_free(info->rects, info->num_rects * | ||
238 | sizeof(drm_clip_rect_t), DRM_MEM_BUFS); | ||
239 | info->num_rects = update.num; | ||
240 | } | ||
241 | |||
242 | DRM_DEBUG("Updated %d cliprects for drawable %d\n", | ||
243 | info->num_rects, id); | ||
244 | break; | ||
245 | default: | ||
246 | DRM_ERROR("Invalid update type %d\n", update.type); | ||
247 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
248 | return DRM_ERR(EINVAL); | ||
249 | } | ||
250 | |||
251 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * Caller must hold the drawable spinlock! | ||
258 | */ | ||
259 | drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) { | ||
260 | unsigned int idx = id / 32, mod = id % 32; | ||
261 | |||
262 | if (idx >= dev->drw_bitfield_length || | ||
263 | !(dev->drw_bitfield[idx] & (1 << mod))) { | ||
264 | DRM_DEBUG("No such drawable %d\n", id); | ||
265 | return NULL; | ||
266 | } | ||
267 | |||
268 | return dev->drw_info[id]; | ||
56 | } | 269 | } |
270 | EXPORT_SYMBOL(drm_get_drawable_info); | ||
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index b366c5b1bd16..59de4a01515f 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -116,6 +116,8 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
116 | [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 116 | [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
117 | 117 | ||
118 | [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, | 118 | [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, |
119 | |||
120 | [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | ||
119 | }; | 121 | }; |
120 | 122 | ||
121 | #define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) | 123 | #define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 7b1d4e8659ba..6f748e194cf9 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -60,6 +60,7 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | |||
60 | int retcode; | 60 | int retcode; |
61 | 61 | ||
62 | spin_lock_init(&dev->count_lock); | 62 | spin_lock_init(&dev->count_lock); |
63 | spin_lock_init(&dev->drw_lock); | ||
63 | init_timer(&dev->timer); | 64 | init_timer(&dev->timer); |
64 | mutex_init(&dev->struct_mutex); | 65 | mutex_init(&dev->struct_mutex); |
65 | mutex_init(&dev->ctxlist_mutex); | 66 | mutex_init(&dev->ctxlist_mutex); |