Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[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 /*
169 * XXX: Need this to initialize sarea pointer and other stuff in dri_drawable_t
170 * to be able to use the DRI_VALIDATE_DRAWABLE_INFO macro, but is it safe to
171 * call without any sync?
172 */
173 if (driUpdateDrawableInfo(dri_draw))
174 {
175 XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
176 free(dri_draw);
177 return 1;
178 }
179
180 *dri_drawable = dri_draw;
181
182 return 0;
183 }
184
185 int driUpdateDrawableInfo(dri_drawable_t *dri_drawable)
186 {
187 assert(dri_drawable);
188
189 if (dri_drawable->cliprects)
190 XFree(dri_drawable->cliprects);
191 if (dri_drawable->back_cliprects)
192 XFree(dri_drawable->back_cliprects);
193
194 DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
195
196 if (!XF86DRIGetDrawableInfo
197 (
198 dri_drawable->dri_screen->display,
199 dri_drawable->dri_screen->num,
200 dri_drawable->x_drawable,
201 &dri_drawable->sarea_index,
202 &dri_drawable->last_sarea_stamp,
203 &dri_drawable->x,
204 &dri_drawable->y,
205 &dri_drawable->w,
206 &dri_drawable->h,
207 &dri_drawable->num_cliprects,
208 &dri_drawable->cliprects,
209 &dri_drawable->back_x,
210 &dri_drawable->back_y,
211 &dri_drawable->num_back_cliprects,
212 &dri_drawable->back_cliprects
213 ))
214 {
215 dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp;
216 dri_drawable->num_cliprects = 0;
217 dri_drawable->cliprects = NULL;
218 dri_drawable->num_back_cliprects = 0;
219 dri_drawable->back_cliprects = 0;
220
221 return 1;
222 }
223 else
224 dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp;
225
226 DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
227
228 return 0;
229 }
230
231 int driDestroyDrawable(dri_drawable_t *dri_drawable)
232 {
233 assert(dri_drawable);
234
235 if (--dri_drawable->refcount == 0)
236 {
237 if (dri_drawable->cliprects)
238 XFree(dri_drawable->cliprects);
239 if (dri_drawable->back_cliprects)
240 XFree(dri_drawable->back_cliprects);
241 drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable);
242 XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable);
243 free(dri_drawable);
244 }
245
246 return 0;
247 }
248
249 int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context)
250 {
251 int evbase, errbase;
252 dri_context_t *dri_ctx;
253
254 assert(dri_screen);
255 assert(visual);
256 assert(dri_context);
257
258 if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
259 return 1;
260
261 dri_ctx = calloc(1, sizeof(dri_context_t));
262
263 if (!dri_ctx)
264 return 1;
265
266 if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context))
267 {
268 free(dri_ctx);
269 return 1;
270 }
271
272 dri_ctx->dri_screen = dri_screen;
273 *dri_context = dri_ctx;
274
275 return 0;
276 }
277
278 int driDestroyContext(dri_context_t *dri_context)
279 {
280 assert(dri_context);
281
282 XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id);
283 free(dri_context);
284
285 return 0;
286 }
287
288 int driCompareVersions(const dri_version_t *v1, const dri_version_t *v2)
289 {
290 return (v1->major == v2->major) && (v1->minor == v2->minor) && (v1->patch == v2->patch);
291 }
292