diff options
Diffstat (limited to 'drivers/gpu/drm/drm_drawable.c')
-rw-r--r-- | drivers/gpu/drm/drm_drawable.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_drawable.c b/drivers/gpu/drm/drm_drawable.c new file mode 100644 index 000000000000..1839c57663c5 --- /dev/null +++ b/drivers/gpu/drm/drm_drawable.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /** | ||
2 | * \file drm_drawable.c | ||
3 | * IOCTLs for drawables | ||
4 | * | ||
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | ||
6 | * \author Gareth Hughes <gareth@valinux.com> | ||
7 | * \author Michel Dänzer <michel@tungstengraphics.com> | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com | ||
12 | * | ||
13 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
14 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
15 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota. | ||
16 | * All Rights Reserved. | ||
17 | * | ||
18 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
19 | * copy of this software and associated documentation files (the "Software"), | ||
20 | * to deal in the Software without restriction, including without limitation | ||
21 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
22 | * and/or sell copies of the Software, and to permit persons to whom the | ||
23 | * Software is furnished to do so, subject to the following conditions: | ||
24 | * | ||
25 | * The above copyright notice and this permission notice (including the next | ||
26 | * paragraph) shall be included in all copies or substantial portions of the | ||
27 | * Software. | ||
28 | * | ||
29 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
30 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
31 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
32 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
33 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
34 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
35 | * OTHER DEALINGS IN THE SOFTWARE. | ||
36 | */ | ||
37 | |||
38 | #include "drmP.h" | ||
39 | |||
40 | /** | ||
41 | * Allocate drawable ID and memory to store information about it. | ||
42 | */ | ||
43 | int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
44 | { | ||
45 | unsigned long irqflags; | ||
46 | struct drm_draw *draw = data; | ||
47 | int new_id = 0; | ||
48 | int ret; | ||
49 | |||
50 | again: | ||
51 | if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) { | ||
52 | DRM_ERROR("Out of memory expanding drawable idr\n"); | ||
53 | return -ENOMEM; | ||
54 | } | ||
55 | |||
56 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
57 | ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id); | ||
58 | if (ret == -EAGAIN) { | ||
59 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
60 | goto again; | ||
61 | } | ||
62 | |||
63 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
64 | |||
65 | draw->handle = new_id; | ||
66 | |||
67 | DRM_DEBUG("%d\n", draw->handle); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * Free drawable ID and memory to store information about it. | ||
74 | */ | ||
75 | int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
76 | { | ||
77 | struct drm_draw *draw = data; | ||
78 | unsigned long irqflags; | ||
79 | |||
80 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
81 | |||
82 | drm_free(drm_get_drawable_info(dev, draw->handle), | ||
83 | sizeof(struct drm_drawable_info), DRM_MEM_BUFS); | ||
84 | |||
85 | idr_remove(&dev->drw_idr, draw->handle); | ||
86 | |||
87 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
88 | DRM_DEBUG("%d\n", draw->handle); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
93 | { | ||
94 | struct drm_update_draw *update = data; | ||
95 | unsigned long irqflags; | ||
96 | struct drm_clip_rect *rects; | ||
97 | struct drm_drawable_info *info; | ||
98 | int err; | ||
99 | |||
100 | info = idr_find(&dev->drw_idr, update->handle); | ||
101 | if (!info) { | ||
102 | info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS); | ||
103 | if (!info) | ||
104 | return -ENOMEM; | ||
105 | if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) { | ||
106 | DRM_ERROR("No such drawable %d\n", update->handle); | ||
107 | drm_free(info, sizeof(*info), DRM_MEM_BUFS); | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | switch (update->type) { | ||
113 | case DRM_DRAWABLE_CLIPRECTS: | ||
114 | if (update->num != info->num_rects) { | ||
115 | rects = drm_alloc(update->num * sizeof(struct drm_clip_rect), | ||
116 | DRM_MEM_BUFS); | ||
117 | } else | ||
118 | rects = info->rects; | ||
119 | |||
120 | if (update->num && !rects) { | ||
121 | DRM_ERROR("Failed to allocate cliprect memory\n"); | ||
122 | err = -ENOMEM; | ||
123 | goto error; | ||
124 | } | ||
125 | |||
126 | if (update->num && DRM_COPY_FROM_USER(rects, | ||
127 | (struct drm_clip_rect __user *) | ||
128 | (unsigned long)update->data, | ||
129 | update->num * | ||
130 | sizeof(*rects))) { | ||
131 | DRM_ERROR("Failed to copy cliprects from userspace\n"); | ||
132 | err = -EFAULT; | ||
133 | goto error; | ||
134 | } | ||
135 | |||
136 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
137 | |||
138 | if (rects != info->rects) { | ||
139 | drm_free(info->rects, info->num_rects * | ||
140 | sizeof(struct drm_clip_rect), DRM_MEM_BUFS); | ||
141 | } | ||
142 | |||
143 | info->rects = rects; | ||
144 | info->num_rects = update->num; | ||
145 | |||
146 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
147 | |||
148 | DRM_DEBUG("Updated %d cliprects for drawable %d\n", | ||
149 | info->num_rects, update->handle); | ||
150 | break; | ||
151 | default: | ||
152 | DRM_ERROR("Invalid update type %d\n", update->type); | ||
153 | return -EINVAL; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | |||
158 | error: | ||
159 | if (rects != info->rects) | ||
160 | drm_free(rects, update->num * sizeof(struct drm_clip_rect), | ||
161 | DRM_MEM_BUFS); | ||
162 | |||
163 | return err; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Caller must hold the drawable spinlock! | ||
168 | */ | ||
169 | struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) | ||
170 | { | ||
171 | return idr_find(&dev->drw_idr, id); | ||
172 | } | ||
173 | EXPORT_SYMBOL(drm_get_drawable_info); | ||
174 | |||
175 | static int drm_drawable_free(int idr, void *p, void *data) | ||
176 | { | ||
177 | struct drm_drawable_info *info = p; | ||
178 | |||
179 | if (info) { | ||
180 | drm_free(info->rects, info->num_rects * | ||
181 | sizeof(struct drm_clip_rect), DRM_MEM_BUFS); | ||
182 | drm_free(info, sizeof(*info), DRM_MEM_BUFS); | ||
183 | } | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | void drm_drawable_free_all(struct drm_device *dev) | ||
189 | { | ||
190 | idr_for_each(&dev->drw_idr, drm_drawable_free, NULL); | ||
191 | idr_remove_all(&dev->drw_idr); | ||
192 | } | ||