Merge branch 'gallium-polygon-stipple'
[mesa.git] / src / gallium / winsys / g3dvl / dri / driclient.c
1 #include "driclient.h"
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <fcntl.h>
5 #include <X11/Xlibint.h>
6
7 int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf)
8 {
9 int evbase, errbase;
10 char *driver_name;
11 int newly_opened;
12 drm_magic_t magic;
13 drmVersionPtr drm_version;
14 drm_handle_t sarea_handle;
15 char *bus_id;
16 dri_screen_t *dri_scrn;
17
18 assert(display);
19 assert(dri_screen);
20
21 if (!XF86DRIQueryExtension(display, &evbase, &errbase))
22 return 1;
23
24 dri_scrn = calloc(1, sizeof(dri_screen_t));
25
26 if (!dri_scrn)
27 return 1;
28
29 if (!XF86DRIQueryVersion(display, &dri_scrn->dri.major, &dri_scrn->dri.minor, &dri_scrn->dri.patch))
30 goto free_screen;
31
32 dri_scrn->display = display;
33 dri_scrn->num = screen;
34 dri_scrn->draw_lock_id = 1;
35
36 if (!XF86DRIOpenConnection(display, screen, &sarea_handle, &bus_id))
37 goto free_screen;
38
39 dri_scrn->fd = -1;
40 dri_scrn->fd = drmOpenOnce(NULL, bus_id, &newly_opened);
41 XFree(bus_id);
42
43 if (dri_scrn->fd < 0)
44 goto close_connection;
45
46 if (drmGetMagic(dri_scrn->fd, &magic))
47 goto close_drm;
48
49 drm_version = drmGetVersion(dri_scrn->fd);
50
51 if (!drm_version)
52 goto close_drm;
53
54 dri_scrn->drm.major = drm_version->version_major;
55 dri_scrn->drm.minor = drm_version->version_minor;
56 dri_scrn->drm.patch = drm_version->version_patchlevel;
57 drmFreeVersion(drm_version);
58
59 if (!XF86DRIAuthConnection(display, screen, magic))
60 goto close_drm;
61
62 if (!XF86DRIGetClientDriverName
63 (
64 display,
65 screen,
66 &dri_scrn->ddx.major,
67 &dri_scrn->ddx.minor,
68 &dri_scrn->ddx.patch,
69 &driver_name
70 ))
71 goto close_drm;
72
73 if (drmMap(dri_scrn->fd, sarea_handle, SAREA_MAX, (drmAddress)&dri_scrn->sarea))
74 goto close_drm;
75
76 dri_scrn->drawable_hash = drmHashCreate();
77
78 if (!dri_scrn->drawable_hash)
79 goto unmap_sarea;
80
81 if (dri_framebuf)
82 {
83 if (!XF86DRIGetDeviceInfo
84 (
85 display,
86 screen, &dri_framebuf->drm_handle,
87 &dri_framebuf->base,
88 &dri_framebuf->size,
89 &dri_framebuf->stride,
90 &dri_framebuf->private_size,
91 &dri_framebuf->private
92 ))
93 goto destroy_hash;
94 }
95
96 *dri_screen = dri_scrn;
97
98 return 0;
99
100 destroy_hash:
101 drmHashDestroy(dri_scrn->drawable_hash);
102 unmap_sarea:
103 drmUnmap(dri_scrn->sarea, SAREA_MAX);
104 close_drm:
105 drmCloseOnce(dri_scrn->fd);
106 close_connection:
107 XF86DRICloseConnection(display, screen);
108 free_screen:
109 free(dri_scrn);
110
111 return 1;
112 }
113
114 int driDestroyScreen(dri_screen_t *dri_screen)
115 {
116 Drawable draw;
117 dri_drawable_t *dri_draw;
118
119 assert(dri_screen);
120
121 if (drmHashFirst(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
122 {
123 dri_draw->refcount = 1;
124 driDestroyDrawable(dri_draw);
125
126 while (drmHashNext(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
127 {
128 dri_draw->refcount = 1;
129 driDestroyDrawable(dri_draw);
130 }
131 }
132
133 drmHashDestroy(dri_screen->drawable_hash);
134 drmUnmap(dri_screen->sarea, SAREA_MAX);
135 drmCloseOnce(dri_screen->fd);
136 XF86DRICloseConnection(dri_screen->display, dri_screen->num);
137 free(dri_screen);
138
139 return 0;
140 }
141
142 int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable)
143 {
144 int evbase, errbase;
145 dri_drawable_t *dri_draw;
146
147 assert(dri_screen);
148 assert(dri_drawable);
149
150 if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
151 return 1;
152
153 if (!drmHashLookup(dri_screen->drawable_hash, drawable, (void**)dri_drawable))
154 {
155 /* Found */
156 (*dri_drawable)->refcount++;
157 return 0;
158 }
159
160 dri_draw = calloc(1, sizeof(dri_drawable_t));
161
162 if (!dri_draw)
163 return 1;
164
165 if (!XF86DRICreateDrawable(dri_screen->display, 0, drawable, &dri_draw->drm_drawable))
166 {
167 free(dri_draw);
168 return 1;
169 }
170
171 dri_draw->x_drawable = drawable;
172 dri_draw->sarea_index = 0;
173 dri_draw->sarea_stamp = NULL;
174 dri_draw->last_sarea_stamp = 0;
175 dri_draw->dri_screen = dri_screen;
176 dri_draw->refcount = 1;
177
178 if (drmHashInsert(dri_screen->drawable_hash, drawable, dri_draw))
179 {
180 XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
181 free(dri_draw);
182 return 1;
183 }
184
185 if (!dri_draw->sarea_stamp || *dri_draw->sarea_stamp != dri_draw->last_sarea_stamp)
186 {
187 DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
188
189 if (driUpdateDrawableInfo(dri_draw))
190 {
191 XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
192 free(dri_draw);
193 DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
194 return 1;
195 }
196
197 DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
198 }
199
200 *dri_drawable = dri_draw;
201
202 return 0;
203 }
204
205 int driUpdateDrawableInfo(dri_drawable_t *dri_drawable)
206 {
207 assert(dri_drawable);
208
209 if (dri_drawable->cliprects)
210 {
211 XFree(dri_drawable->cliprects);
212 dri_drawable->cliprects = NULL;
213 }
214 if (dri_drawable->back_cliprects)
215 {
216 XFree(dri_drawable->back_cliprects);
217 dri_drawable->back_cliprects = NULL;
218 }
219
220 DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
221
222 if (!XF86DRIGetDrawableInfo
223 (
224 dri_drawable->dri_screen->display,
225 dri_drawable->dri_screen->num,
226 dri_drawable->x_drawable,
227 &dri_drawable->sarea_index,
228 &dri_drawable->last_sarea_stamp,
229 &dri_drawable->x,
230 &dri_drawable->y,
231 &dri_drawable->w,
232 &dri_drawable->h,
233 &dri_drawable->num_cliprects,
234 &dri_drawable->cliprects,
235 &dri_drawable->back_x,
236 &dri_drawable->back_y,
237 &dri_drawable->num_back_cliprects,
238 &dri_drawable->back_cliprects
239 ))
240 {
241 dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp;
242 dri_drawable->num_cliprects = 0;
243 dri_drawable->cliprects = NULL;
244 dri_drawable->num_back_cliprects = 0;
245 dri_drawable->back_cliprects = 0;
246
247 return 1;
248 }
249 else
250 dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp;
251
252 DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
253
254 return 0;
255 }
256
257 int driDestroyDrawable(dri_drawable_t *dri_drawable)
258 {
259 assert(dri_drawable);
260
261 if (--dri_drawable->refcount == 0)
262 {
263 if (dri_drawable->cliprects)
264 XFree(dri_drawable->cliprects);
265 if (dri_drawable->back_cliprects)
266 XFree(dri_drawable->back_cliprects);
267 drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable);
268 XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable);
269 free(dri_drawable);
270 }
271
272 return 0;
273 }
274
275 int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context)
276 {
277 int evbase, errbase;
278 dri_context_t *dri_ctx;
279
280 assert(dri_screen);
281 assert(visual);
282 assert(dri_context);
283
284 if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
285 return 1;
286
287 dri_ctx = calloc(1, sizeof(dri_context_t));
288
289 if (!dri_ctx)
290 return 1;
291
292 if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context))
293 {
294 free(dri_ctx);
295 return 1;
296 }
297
298 dri_ctx->dri_screen = dri_screen;
299 *dri_context = dri_ctx;
300
301 return 0;
302 }
303
304 int driDestroyContext(dri_context_t *dri_context)
305 {
306 assert(dri_context);
307
308 XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id);
309 free(dri_context);
310
311 return 0;
312 }
313
314 int dri2CreateScreen(Display *display, int screen, dri_screen_t **dri_screen)
315 {
316 dri_screen_t *dri_scrn;
317 drm_magic_t magic;
318 char *drvName;
319 char *devName;
320
321 dri_scrn = calloc(1, sizeof(dri_screen_t));
322
323 if (!dri_scrn)
324 return 1;
325
326 if (!DRI2Connect(display, XRootWindow(display, screen), &drvName, &devName))
327 goto free_screen;
328
329 dri_scrn->fd = open(devName, O_RDWR);
330 Xfree(drvName);
331 Xfree(devName);
332 if (dri_scrn->fd < 0)
333 goto free_screen;
334
335 if (drmGetMagic(dri_scrn->fd, &magic))
336 goto free_screen;
337
338 if (!DRI2Authenticate(display, RootWindow(display, screen), magic))
339 goto free_screen;
340
341 dri_scrn->display = display;
342 dri_scrn->num = screen;
343 *dri_screen = dri_scrn;
344
345 return 0;
346
347 free_screen:
348 free(dri_scrn);
349
350 return 1;
351 }
352
353 int dri2DestroyScreen(dri_screen_t *dri_screen)
354 {
355 /* Not much to do here apparently... */
356 assert(dri_screen);
357 free(dri_screen);
358 return 0;
359 }
360
361 int dri2CreateDrawable(dri_screen_t *dri_screen, XID drawable)
362 {
363 assert(dri_screen);
364 DRI2CreateDrawable(dri_screen->display, drawable);
365 return 0;
366 }
367
368 int dri2DestroyDrawable(dri_screen_t *dri_screen, XID drawable)
369 {
370 assert(dri_screen);
371 DRI2DestroyDrawable(dri_screen->display, drawable);
372 return 0;
373 }
374
375 int dri2CopyDrawable(dri_screen_t *dri_screen, XID drawable, int dest, int src)
376 {
377 XserverRegion region;
378
379 assert(dri_screen);
380 assert(dest >= DRI_BUFFER_FRONT_LEFT && dest <= DRI_BUFFER_DEPTH_STENCIL);
381 assert(src >= DRI_BUFFER_FRONT_LEFT && src <= DRI_BUFFER_DEPTH_STENCIL);
382
383 region = XFixesCreateRegionFromWindow(dri_screen->display, drawable, WindowRegionBounding);
384 DRI2CopyRegion(dri_screen->display, drawable, region, dest, src);
385 XFixesDestroyRegion(dri_screen->display, region);
386
387 return 0;
388 }