aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_drawable.c
diff options
context:
space:
mode:
author=?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com>2006-10-24 09:04:19 -0400
committerairlied <airlied@linux.ie>2006-12-06 23:53:28 -0500
commitbea5679f9cb97b7e41786c8500df56665cd21e56 (patch)
tree8259fc9d75730be3db028892f0da991dec54e37e /drivers/char/drm/drm_drawable.c
parent68815bad7239989d92f315c10d9ef65a11945a75 (diff)
drm: Add support for tracking drawable information to core
Actually make the existing ioctls for adding and removing drawables do something useful, and add another ioctl for the X server to update drawable information. The only kind of drawable information tracked so far is cliprects. Only reallocate cliprect memory if the number of cliprects changes. Also improve diagnostic output. hook up drm ioctl update draw export drm_get_drawable_info symbol Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/drm_drawable.c')
-rw-r--r--drivers/char/drm/drm_drawable.c230
1 files changed, 222 insertions, 8 deletions
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. */
39int drm_adddraw(struct inode *inode, struct file *filp, 40int 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 }
59done:
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. */
52int drm_rmdraw(struct inode *inode, struct file *filp, 112int 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
173int 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 */
259drm_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}
270EXPORT_SYMBOL(drm_get_drawable_info);