aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
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
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')
-rw-r--r--drivers/char/drm/drm.h24
-rw-r--r--drivers/char/drm/drmP.h13
-rw-r--r--drivers/char/drm/drm_drawable.c230
-rw-r--r--drivers/char/drm/drm_drv.c2
-rw-r--r--drivers/char/drm/drm_stub.c1
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 */
122typedef 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 */
122typedef struct drm_tex_region { 130typedef 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 */
457typedef enum {
458 DRM_DRAWABLE_CLIPRECTS,
459} drm_drawable_info_type_t;
460
461typedef 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 */
449typedef struct drm_auth { 471typedef 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
747static __inline__ int drm_core_check_feature(struct drm_device *dev, 756static __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);
890extern int drm_rmdraw(struct inode *inode, struct file *filp, 899extern int drm_rmdraw(struct inode *inode, struct file *filp,
891 unsigned int cmd, unsigned long arg); 900 unsigned int cmd, unsigned long arg);
901extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
902 unsigned int cmd, unsigned long arg);
903extern 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) */
894extern int drm_getmagic(struct inode *inode, struct file *filp, 907extern 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. */
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);
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);