drm: Use an include directory hierarchy similar to the Linux one
[dragonfly.git] / sys / dev / drm / drm_drawable.c
1 /*-
2  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
3  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Rickard E. (Rik) Faith <faith@valinux.com>
27  *    Gareth Hughes <gareth@valinux.com>
28  *
29  * $FreeBSD: src/sys/dev/drm2/drm_drawable.c,v 1.1 2012/05/22 11:07:44 kib Exp $
30  */
31
32 /** @file drm_drawable.c
33  * This file implements ioctls to store information along with DRM drawables,
34  * such as the current set of cliprects for vblank-synced buffer swaps.
35  */
36
37 #include <drm/drmP.h>
38
39 struct bsd_drm_drawable_info {
40         struct drm_drawable_info info;
41         int handle;
42         RB_ENTRY(bsd_drm_drawable_info) tree;
43 };
44
45 static int
46 drm_drawable_compare(struct bsd_drm_drawable_info *a,
47     struct bsd_drm_drawable_info *b)
48 {
49         if (a->handle > b->handle)
50                 return 1;
51         if (a->handle < b->handle)
52                 return -1;
53         return 0;
54 }
55
56 RB_PROTOTYPE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
57     drm_drawable_compare);
58 RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
59     drm_drawable_compare);
60
61 struct drm_drawable_info *
62 drm_get_drawable_info(struct drm_device *dev, int handle)
63 {
64         struct bsd_drm_drawable_info find, *result;
65
66         find.handle = handle;
67         result = RB_FIND(drawable_tree, &dev->drw_head, &find);
68
69         return &result->info;
70 }
71
72 int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
73 {
74         struct drm_draw *draw = data;
75         struct bsd_drm_drawable_info *info;
76
77         info = kmalloc(sizeof(struct bsd_drm_drawable_info), DRM_MEM_DRAWABLE,
78             M_NOWAIT | M_ZERO);
79         if (info == NULL)
80                 return ENOMEM;
81
82         info->handle = alloc_unr(dev->drw_unrhdr);
83         spin_lock(&dev->drw_lock);
84         RB_INSERT(drawable_tree, &dev->drw_head, info);
85         draw->handle = info->handle;
86         spin_unlock(&dev->drw_lock);
87
88         DRM_DEBUG("%d\n", draw->handle);
89
90         return 0;
91 }
92
93 int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
94 {
95         struct drm_draw *draw = (struct drm_draw *)data;
96         struct drm_drawable_info *info;
97
98         spin_lock(&dev->drw_lock);
99         info = drm_get_drawable_info(dev, draw->handle);
100         if (info != NULL) {
101                 RB_REMOVE(drawable_tree, &dev->drw_head,
102                     (struct bsd_drm_drawable_info *)info);
103                 spin_unlock(&dev->drw_lock);
104                 free_unr(dev->drw_unrhdr, draw->handle);
105                 drm_free(info->rects, DRM_MEM_DRAWABLE);
106                 drm_free(info, DRM_MEM_DRAWABLE);
107                 return 0;
108         } else {
109                 spin_unlock(&dev->drw_lock);
110                 return EINVAL;
111         }
112 }
113
114 int drm_update_draw(struct drm_device *dev, void *data,
115                     struct drm_file *file_priv)
116 {
117         struct drm_drawable_info *info;
118         struct drm_update_draw *update = (struct drm_update_draw *)data;
119         int ret;
120
121         info = drm_get_drawable_info(dev, update->handle);
122         if (info == NULL)
123                 return EINVAL;
124
125         switch (update->type) {
126         case DRM_DRAWABLE_CLIPRECTS:
127                 spin_lock(&dev->drw_lock);
128                 if (update->num != info->num_rects) {
129                         drm_free(info->rects, DRM_MEM_DRAWABLE);
130                         info->rects = NULL;
131                         info->num_rects = 0;
132                 }
133                 if (update->num == 0) {
134                         spin_unlock(&dev->drw_lock);
135                         return 0;
136                 }
137                 if (info->rects == NULL) {
138                         info->rects = kmalloc(sizeof(*info->rects) *
139                             update->num, DRM_MEM_DRAWABLE, M_NOWAIT);
140                         if (info->rects == NULL) {
141                                 spin_unlock(&dev->drw_lock);
142                                 return ENOMEM;
143                         }
144                         info->num_rects = update->num;
145                 }
146                 /* For some reason the pointer arg is unsigned long long. */
147                 ret = copyin((void *)(intptr_t)update->data, info->rects,
148                     sizeof(*info->rects) * info->num_rects);
149                 spin_unlock(&dev->drw_lock);
150                 return ret;
151         default:
152                 return EINVAL;
153         }
154 }
155
156 void drm_drawable_free_all(struct drm_device *dev)
157 {
158         struct bsd_drm_drawable_info *info, *next;
159
160         spin_lock(&dev->drw_lock);
161         for (info = RB_MIN(drawable_tree, &dev->drw_head);
162             info != NULL ; info = next) {
163                 next = RB_NEXT(drawable_tree, &dev->drw_head, info);
164                 RB_REMOVE(drawable_tree, &dev->drw_head,
165                     (struct bsd_drm_drawable_info *)info);
166                 spin_unlock(&dev->drw_lock);
167                 free_unr(dev->drw_unrhdr, info->handle);
168                 drm_free(info->info.rects, DRM_MEM_DRAWABLE);
169                 drm_free(info, DRM_MEM_DRAWABLE);
170                 spin_lock(&dev->drw_lock);
171         }
172         spin_unlock(&dev->drw_lock);
173 }