randr12: better handling for output types in nv_crtc
[nouveau] / src / nouveau_grobj.c
1 /*
2  * Copyright 2007 Nouveau Project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <errno.h>
25
26 #include "nouveau_drmif.h"
27
28 int
29 nouveau_grobj_alloc(struct nouveau_channel *userchan, uint32_t handle,
30                     int class, struct nouveau_grobj **usergrobj)
31 {
32         struct nouveau_device_priv *nv = nouveau_device(userchan->device);
33         struct nouveau_grobj_priv *gr;
34         struct drm_nouveau_grobj_alloc g;
35         int ret;
36
37         if (!nv || !usergrobj || *usergrobj)
38                 return -EINVAL;
39
40         gr = calloc(1, sizeof(*gr));
41         if (!gr)
42                 return -ENOMEM;
43         gr->base.channel = userchan;
44         gr->base.handle  = handle;
45         gr->base.grclass = class;
46
47         g.channel = userchan->id;
48         g.handle  = handle;
49         g.class   = class;
50         ret = drmCommandWrite(nv->fd, DRM_NOUVEAU_GROBJ_ALLOC, &g, sizeof(g));
51         if (ret) {
52                 nouveau_grobj_free((void *)&gr);
53                 return ret;
54         }
55
56         *usergrobj = &gr->base;
57         return 0;
58 }
59
60 int
61 nouveau_grobj_ref(struct nouveau_channel *userchan, uint32_t handle,
62                   struct nouveau_grobj **usergr)
63 {
64         struct nouveau_grobj_priv *gr;
65
66         if (!userchan || !usergr || *usergr)
67                 return -EINVAL;
68
69         gr = calloc(1, sizeof(*gr));
70         if (!gr)
71                 return -ENOMEM;
72         gr->base.channel = userchan;
73         gr->base.handle = handle;
74         gr->base.grclass = 0;
75
76         *usergr = &gr->base;
77         return 0;
78 }
79
80 void
81 nouveau_grobj_free(struct nouveau_grobj **usergrobj)
82 {
83         struct nouveau_grobj_priv *gr;
84
85         if (!usergrobj)
86                 return;
87         gr = nouveau_grobj(*usergrobj);
88         *usergrobj = NULL;
89
90         if (gr) {
91                 struct nouveau_channel_priv *chan;
92                 struct nouveau_device_priv *nv;
93                 struct drm_nouveau_gpuobj_free f;
94
95                 chan = nouveau_channel(gr->base.channel);
96                 nv   = nouveau_device(chan->base.device);
97
98                 if (gr->base.grclass) {
99                         f.channel = chan->drm.channel;
100                         f.handle  = gr->base.handle;
101                         drmCommandWrite(nv->fd, DRM_NOUVEAU_GPUOBJ_FREE,
102                                         &f, sizeof(f)); 
103                 }
104                 free(gr);
105         }
106 }
107