Merge remote branch 'upstream/gallium-0.2' into nouveau-gallium-0.2
[mesa.git] / src / driclient / src / driclient.c
1 #include "driclient.h"
2 #include <assert.h>
3 #include <stdlib.h>
4
5 int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf)
6 {
7 int evbase, errbase;
8 char *driver_name;
9 int newly_opened;
10 drm_magic_t magic;
11 drmVersionPtr drm_version;
12 drm_handle_t sarea_handle;
13 char *bus_id;
14 dri_screen_t *dri_scrn;
15
16 assert(display);
17 assert(dri_screen);
18
19 if (!XF86DRIQueryExtension(display, &evbase, &errbase))
20 return 1;
21
22 dri_scrn = calloc(1, sizeof(dri_screen_t));
23
24 if (!dri_scrn)
25 return 1;
26
27 if (!XF86DRIQueryVersion(display, &dri_scrn->dri.major, &dri_scrn->dri.minor, &dri_scrn->dri.patch))
28 goto free_screen;
29
30 dri_scrn->display = display;
31 dri_scrn->num = screen;
32 dri_scrn->draw_lock_id = 1;
33
34 if (!XF86DRIOpenConnection(display, screen, &sarea_handle, &bus_id))
35 goto free_screen;
36
37 dri_scrn->fd = -1;
38 dri_scrn->fd = drmOpenOnce(NULL, bus_id, &newly_opened);
39 XFree(bus_id);
40
41 if (dri_scrn->fd < 0)
42 goto close_connection;
43
44 if (drmGetMagic(dri_scrn->fd, &magic))
45 goto close_drm;
46
47 drm_version = drmGetVersion(dri_scrn->fd);
48
49 if (!drm_version)
50 goto close_drm;
51
52 dri_scrn->drm.major = drm_version->version_major;
53 dri_scrn->drm.minor = drm_version->version_minor;
54 dri_scrn->drm.patch = drm_version->version_patchlevel;
55 drmFreeVersion(drm_version);
56
57 if (!XF86DRIAuthConnection(display, screen, magic))
58 goto close_drm;
59
60 if (!XF86DRIGetClientDriverName
61 (
62 display,
63 screen,
64 &dri_scrn->ddx.major,
65 &dri_scrn->ddx.minor,
66 &dri_scrn->ddx.patch,
67 &driver_name
68 ))
69 goto close_drm;
70
71 if (drmMap(dri_scrn->fd, sarea_handle, SAREA_MAX, (drmAddress)&dri_scrn->sarea))
72 goto close_drm;
73
74 dri_scrn->drawable_hash = drmHashCreate();
75
76 if (!dri_scrn->drawable_hash)
77 goto unmap_sarea;
78
79 if (dri_framebuf)
80 {
81 if (!XF86DRIGetDeviceInfo
82 (
83 display,
84 screen, &dri_framebuf->drm_handle,
85 &dri_framebuf->base,
86 &dri_framebuf->size,
87 &dri_framebuf->stride,
88 &dri_framebuf->private_size,
89 &dri_framebuf->private
90 ))
91 goto destroy_hash;
92 }
93
94 *dri_screen = dri_scrn;
95
96 return 0;
97
98 destroy_hash:
99 drmHashDestroy(dri_scrn->drawable_hash);
100 unmap_sarea:
101 drmUnmap(dri_scrn->sarea, SAREA_MAX);
102 close_drm:
103 drmCloseOnce(dri_scrn->fd);
104 close_connection:
105 XF86DRICloseConnection(display, screen);
106 free_screen:
107 free(dri_scrn);
108
109 return 1;
110 }
111
112 int driDestroyScreen(dri_screen_t *dri_screen)
113 {
114 assert(dri_screen);
115
116 drmHashDestroy(dri_screen->drawable_hash);
117 drmUnmap(dri_screen->sarea, SAREA_MAX);
118 drmCloseOnce(dri_screen->fd);
119 XF86DRICloseConnection(dri_screen->display, dri_screen->num);
120 free(dri_screen);
121
122 return 0;
123 }
124
125 int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable)
126 {
127 int evbase, errbase;
128 dri_drawable_t *dri_draw;
129
130 assert(dri_screen);
131 assert(dri_drawable);
132
133 if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
134 return 1;
135
136 if (!drmHashLookup(dri_screen->drawable_hash, drawable, (void**)dri_drawable))
137 {
138 /* Found */
139 (*dri_drawable)->refcount++;
140 return 0;
141 }
142
143 dri_draw = calloc(1, sizeof(dri_drawable_t));
144
145 if (!dri_draw)
146 return 1;
147
148 if (!XF86DRICreateDrawable(dri_screen->display, 0, drawable, &dri_draw->drm_drawable))
149 {
150 free(dri_draw);
151 return 1;
152 }
153
154 dri_draw->x_drawable = drawable;
155 dri_draw->sarea_index = 0;
156 dri_draw->sarea_stamp = NULL;
157 dri_draw->last_sarea_stamp = 0;
158 dri_draw->dri_screen = dri_screen;
159 dri_draw->refcount = 1;
160
161 if (drmHashInsert(dri_screen->drawable_hash, drawable, dri_draw))
162 {
163 XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
164 free(dri_draw);
165 return 1;
166 }
167
168 if (!dri_draw->sarea_stamp || *dri_draw->sarea_stamp != dri_draw->last_sarea_stamp)
169 {
170 DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
171
172 if (driUpdateDrawableInfo(dri_draw))
173 {
174 XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
175 free(dri_draw);
176 DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
177 return 1;
178 }
179
180 DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
181 }
182
183 *dri_drawable = dri_draw;
184
185 return 0;
186 }
187
188 int driUpdateDrawableInfo(dri_drawable_t *dri_drawable)
189 {
190 assert(dri_drawable);
191
192 if (dri_drawable->cliprects)
193 {
194 XFree(dri_drawable->cliprects);
195 dri_drawable->cliprects = NULL;
196 }
197 if (dri_drawable->back_cliprects)
198 {
199 XFree(dri_drawable->back_cliprects);
200 dri_drawable->back_cliprects = NULL;
201 }
202
203 DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
204
205 if (!XF86DRIGetDrawableInfo
206 (
207 dri_drawable->dri_screen->display,
208 dri_drawable->dri_screen->num,
209 dri_drawable->x_drawable,
210 &dri_drawable->sarea_index,
211 &dri_drawable->last_sarea_stamp,
212 &dri_drawable->x,
213 &dri_drawable->y,
214 &dri_drawable->w,
215 &dri_drawable->h,
216 &dri_drawable->num_cliprects,
217 &dri_drawable->cliprects,
218 &dri_drawable->back_x,
219 &dri_drawable->back_y,
220 &dri_drawable->num_back_cliprects,
221 &dri_drawable->back_cliprects
222 ))
223 {
224 dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp;
225 dri_drawable->num_cliprects = 0;
226 dri_drawable->cliprects = NULL;
227 dri_drawable->num_back_cliprects = 0;
228 dri_drawable->back_cliprects = 0;
229
230 return 1;
231 }
232 else
233 dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp;
234
235 DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
236
237 return 0;
238 }
239
240 int driDestroyDrawable(dri_drawable_t *dri_drawable)
241 {
242 assert(dri_drawable);
243
244 if (--dri_drawable->refcount == 0)
245 {
246 if (dri_drawable->cliprects)
247 XFree(dri_drawable->cliprects);
248 if (dri_drawable->back_cliprects)
249 XFree(dri_drawable->back_cliprects);
250 drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable);
251 XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable);
252 free(dri_drawable);
253 }
254
255 return 0;
256 }
257
258 int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context)
259 {
260 int evbase, errbase;
261 dri_context_t *dri_ctx;
262
263 assert(dri_screen);
264 assert(visual);
265 assert(dri_context);
266
267 if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
268 return 1;
269
270 dri_ctx = calloc(1, sizeof(dri_context_t));
271
272 if (!dri_ctx)
273 return 1;
274
275 if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context))
276 {
277 free(dri_ctx);
278 return 1;
279 }
280
281 dri_ctx->dri_screen = dri_screen;
282 *dri_context = dri_ctx;
283
284 return 0;
285 }
286
287 int driDestroyContext(dri_context_t *dri_context)
288 {
289 assert(dri_context);
290
291 XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id);
292 free(dri_context);
293
294 return 0;
295 }