Merge commit 'origin/gallium-winsys-handle-rebased'
[mesa.git] / src / glx / XF86dri.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 Copyright 2000 VA Linux Systems, Inc.
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sub license, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice (including the
16 next paragraph) shall be included in all copies or substantial portions
17 of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Kevin E. Martin <martin@valinux.com>
32 * Jens Owen <jens@tungstengraphics.com>
33 * Rickard E. (Rik) Faith <faith@valinux.com>
34 *
35 */
36
37 /* THIS IS NOT AN X CONSORTIUM STANDARD */
38
39 #ifdef GLX_DIRECT_RENDERING
40
41 #define NEED_REPLIES
42 #include <X11/Xlibint.h>
43 #include <X11/extensions/Xext.h>
44 #include <X11/extensions/extutil.h>
45 #include "xf86dristr.h"
46
47
48 #if defined(__GNUC__)
49 # define PUBLIC __attribute__((visibility("default")))
50 # define USED __attribute__((used))
51 #else
52 # define PUBLIC
53 # define USED
54 #endif
55
56
57
58 static XExtensionInfo _xf86dri_info_data;
59 static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
60 static char xf86dri_extension_name[] = XF86DRINAME;
61
62 #define XF86DRICheckExtension(dpy,i,val) \
63 XextCheckExtension (dpy, i, xf86dri_extension_name, val)
64
65 /*****************************************************************************
66 * *
67 * private utility routines *
68 * *
69 *****************************************************************************/
70
71 static int close_display(Display * dpy, XExtCodes * extCodes);
72 static /* const */ XExtensionHooks xf86dri_extension_hooks = {
73 NULL, /* create_gc */
74 NULL, /* copy_gc */
75 NULL, /* flush_gc */
76 NULL, /* free_gc */
77 NULL, /* create_font */
78 NULL, /* free_font */
79 close_display, /* close_display */
80 NULL, /* wire_to_event */
81 NULL, /* event_to_wire */
82 NULL, /* error */
83 NULL, /* error_string */
84 };
85
86 static
87 XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info,
88 xf86dri_extension_name,
89 &xf86dri_extension_hooks, 0, NULL)
90
91 static
92 XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info)
93
94
95 /*****************************************************************************
96 * *
97 * public XFree86-DRI Extension routines *
98 * *
99 *****************************************************************************/
100 #if 0
101 #include <stdio.h>
102 #define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg);
103 #else
104 #define TRACE(msg)
105 #endif
106
107 Bool
108 XF86DRIQueryExtension(Display * dpy, int *event_basep,
109 int *error_basep)
110 {
111 XExtDisplayInfo *info = find_display(dpy);
112
113 TRACE("QueryExtension...");
114 if (XextHasExtension(info)) {
115 *event_basep = info->codes->first_event;
116 *error_basep = info->codes->first_error;
117 TRACE("QueryExtension... return True");
118 return True;
119 }
120 else {
121 TRACE("QueryExtension... return False");
122 return False;
123 }
124 }
125
126 Bool
127 XF86DRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion,
128 int *patchVersion)
129 {
130 XExtDisplayInfo *info = find_display(dpy);
131 xXF86DRIQueryVersionReply rep;
132 xXF86DRIQueryVersionReq *req;
133
134 TRACE("QueryVersion...");
135 XF86DRICheckExtension(dpy, info, False);
136
137 LockDisplay(dpy);
138 GetReq(XF86DRIQueryVersion, req);
139 req->reqType = info->codes->major_opcode;
140 req->driReqType = X_XF86DRIQueryVersion;
141 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
142 UnlockDisplay(dpy);
143 SyncHandle();
144 TRACE("QueryVersion... return False");
145 return False;
146 }
147 *majorVersion = rep.majorVersion;
148 *minorVersion = rep.minorVersion;
149 *patchVersion = rep.patchVersion;
150 UnlockDisplay(dpy);
151 SyncHandle();
152 TRACE("QueryVersion... return True");
153 return True;
154 }
155
156 Bool
157 XF86DRIQueryDirectRenderingCapable(Display * dpy, int screen,
158 Bool * isCapable)
159 {
160 XExtDisplayInfo *info = find_display(dpy);
161 xXF86DRIQueryDirectRenderingCapableReply rep;
162 xXF86DRIQueryDirectRenderingCapableReq *req;
163
164 TRACE("QueryDirectRenderingCapable...");
165 XF86DRICheckExtension(dpy, info, False);
166
167 LockDisplay(dpy);
168 GetReq(XF86DRIQueryDirectRenderingCapable, req);
169 req->reqType = info->codes->major_opcode;
170 req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
171 req->screen = screen;
172 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
173 UnlockDisplay(dpy);
174 SyncHandle();
175 TRACE("QueryDirectRenderingCapable... return False");
176 return False;
177 }
178 *isCapable = rep.isCapable;
179 UnlockDisplay(dpy);
180 SyncHandle();
181 TRACE("QueryDirectRenderingCapable... return True");
182 return True;
183 }
184
185 Bool
186 XF86DRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA,
187 char **busIdString)
188 {
189 XExtDisplayInfo *info = find_display(dpy);
190 xXF86DRIOpenConnectionReply rep;
191 xXF86DRIOpenConnectionReq *req;
192
193 TRACE("OpenConnection...");
194 XF86DRICheckExtension(dpy, info, False);
195
196 LockDisplay(dpy);
197 GetReq(XF86DRIOpenConnection, req);
198 req->reqType = info->codes->major_opcode;
199 req->driReqType = X_XF86DRIOpenConnection;
200 req->screen = screen;
201 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
202 UnlockDisplay(dpy);
203 SyncHandle();
204 TRACE("OpenConnection... return False");
205 return False;
206 }
207
208 *hSAREA = rep.hSAREALow;
209 if (sizeof(drm_handle_t) == 8) {
210 int shift = 32; /* var to prevent warning on next line */
211 *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
212 }
213
214 if (rep.length) {
215 if (!(*busIdString = (char *) Xcalloc(rep.busIdStringLength + 1, 1))) {
216 _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3));
217 UnlockDisplay(dpy);
218 SyncHandle();
219 TRACE("OpenConnection... return False");
220 return False;
221 }
222 _XReadPad(dpy, *busIdString, rep.busIdStringLength);
223 }
224 else {
225 *busIdString = NULL;
226 }
227 UnlockDisplay(dpy);
228 SyncHandle();
229 TRACE("OpenConnection... return True");
230 return True;
231 }
232
233 Bool
234 XF86DRIAuthConnection(Display * dpy, int screen, drm_magic_t magic)
235 {
236 XExtDisplayInfo *info = find_display(dpy);
237 xXF86DRIAuthConnectionReq *req;
238 xXF86DRIAuthConnectionReply rep;
239
240 TRACE("AuthConnection...");
241 XF86DRICheckExtension(dpy, info, False);
242
243 LockDisplay(dpy);
244 GetReq(XF86DRIAuthConnection, req);
245 req->reqType = info->codes->major_opcode;
246 req->driReqType = X_XF86DRIAuthConnection;
247 req->screen = screen;
248 req->magic = magic;
249 rep.authenticated = 0;
250 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) {
251 UnlockDisplay(dpy);
252 SyncHandle();
253 TRACE("AuthConnection... return False");
254 return False;
255 }
256 UnlockDisplay(dpy);
257 SyncHandle();
258 TRACE("AuthConnection... return True");
259 return True;
260 }
261
262 Bool
263 XF86DRICloseConnection(Display * dpy, int screen)
264 {
265 XExtDisplayInfo *info = find_display(dpy);
266 xXF86DRICloseConnectionReq *req;
267
268 TRACE("CloseConnection...");
269
270 XF86DRICheckExtension(dpy, info, False);
271
272 LockDisplay(dpy);
273 GetReq(XF86DRICloseConnection, req);
274 req->reqType = info->codes->major_opcode;
275 req->driReqType = X_XF86DRICloseConnection;
276 req->screen = screen;
277 UnlockDisplay(dpy);
278 SyncHandle();
279 TRACE("CloseConnection... return True");
280 return True;
281 }
282
283 Bool
284 XF86DRIGetClientDriverName(Display * dpy, int screen,
285 int *ddxDriverMajorVersion,
286 int *ddxDriverMinorVersion,
287 int *ddxDriverPatchVersion,
288 char **clientDriverName)
289 {
290 XExtDisplayInfo *info = find_display(dpy);
291 xXF86DRIGetClientDriverNameReply rep;
292 xXF86DRIGetClientDriverNameReq *req;
293
294 TRACE("GetClientDriverName...");
295 XF86DRICheckExtension(dpy, info, False);
296
297 LockDisplay(dpy);
298 GetReq(XF86DRIGetClientDriverName, req);
299 req->reqType = info->codes->major_opcode;
300 req->driReqType = X_XF86DRIGetClientDriverName;
301 req->screen = screen;
302 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
303 UnlockDisplay(dpy);
304 SyncHandle();
305 TRACE("GetClientDriverName... return False");
306 return False;
307 }
308
309 *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
310 *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
311 *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
312
313 if (rep.length) {
314 if (!
315 (*clientDriverName =
316 (char *) Xcalloc(rep.clientDriverNameLength + 1, 1))) {
317 _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3));
318 UnlockDisplay(dpy);
319 SyncHandle();
320 TRACE("GetClientDriverName... return False");
321 return False;
322 }
323 _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
324 }
325 else {
326 *clientDriverName = NULL;
327 }
328 UnlockDisplay(dpy);
329 SyncHandle();
330 TRACE("GetClientDriverName... return True");
331 return True;
332 }
333
334 Bool
335 XF86DRICreateContextWithConfig(Display * dpy, int screen, int configID,
336 XID * context, drm_context_t * hHWContext)
337 {
338 XExtDisplayInfo *info = find_display(dpy);
339 xXF86DRICreateContextReply rep;
340 xXF86DRICreateContextReq *req;
341
342 TRACE("CreateContext...");
343 XF86DRICheckExtension(dpy, info, False);
344
345 LockDisplay(dpy);
346 GetReq(XF86DRICreateContext, req);
347 req->reqType = info->codes->major_opcode;
348 req->driReqType = X_XF86DRICreateContext;
349 req->visual = configID;
350 req->screen = screen;
351 *context = XAllocID(dpy);
352 req->context = *context;
353 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
354 UnlockDisplay(dpy);
355 SyncHandle();
356 TRACE("CreateContext... return False");
357 return False;
358 }
359 *hHWContext = rep.hHWContext;
360 UnlockDisplay(dpy);
361 SyncHandle();
362 TRACE("CreateContext... return True");
363 return True;
364 }
365
366 Bool
367 XF86DRICreateContext(Display * dpy, int screen, Visual * visual,
368 XID * context, drm_context_t * hHWContext)
369 {
370 return XF86DRICreateContextWithConfig(dpy, screen, visual->visualid,
371 context, hHWContext);
372 }
373
374 Bool
375 XF86DRIDestroyContext(Display * dpy, int screen, XID context)
376 {
377 XExtDisplayInfo *info = find_display(dpy);
378 xXF86DRIDestroyContextReq *req;
379
380 TRACE("DestroyContext...");
381 XF86DRICheckExtension(dpy, info, False);
382
383 LockDisplay(dpy);
384 GetReq(XF86DRIDestroyContext, req);
385 req->reqType = info->codes->major_opcode;
386 req->driReqType = X_XF86DRIDestroyContext;
387 req->screen = screen;
388 req->context = context;
389 UnlockDisplay(dpy);
390 SyncHandle();
391 TRACE("DestroyContext... return True");
392 return True;
393 }
394
395 Bool
396 XF86DRICreateDrawable(Display * dpy, int screen,
397 XID drawable, drm_drawable_t * hHWDrawable)
398 {
399 XExtDisplayInfo *info = find_display(dpy);
400 xXF86DRICreateDrawableReply rep;
401 xXF86DRICreateDrawableReq *req;
402
403 TRACE("CreateDrawable...");
404 XF86DRICheckExtension(dpy, info, False);
405
406 LockDisplay(dpy);
407 GetReq(XF86DRICreateDrawable, req);
408 req->reqType = info->codes->major_opcode;
409 req->driReqType = X_XF86DRICreateDrawable;
410 req->screen = screen;
411 req->drawable = drawable;
412 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
413 UnlockDisplay(dpy);
414 SyncHandle();
415 TRACE("CreateDrawable... return False");
416 return False;
417 }
418 *hHWDrawable = rep.hHWDrawable;
419 UnlockDisplay(dpy);
420 SyncHandle();
421 TRACE("CreateDrawable... return True");
422 return True;
423 }
424
425 static int
426 noopErrorHandler(Display * dpy, XErrorEvent * xerr)
427 {
428 return 0;
429 }
430
431 Bool
432 XF86DRIDestroyDrawable(Display * dpy, int screen, XID drawable)
433 {
434 XExtDisplayInfo *info = find_display(dpy);
435 xXF86DRIDestroyDrawableReq *req;
436 int (*oldXErrorHandler) (Display *, XErrorEvent *);
437
438 TRACE("DestroyDrawable...");
439 XF86DRICheckExtension(dpy, info, False);
440
441 /* This is called from the DRI driver, which used call it like this
442 *
443 * if (windowExists(drawable))
444 * destroyDrawable(drawable);
445 *
446 * which is a textbook race condition - the window may disappear
447 * from the server between checking for its existance and
448 * destroying it. Instead we change the semantics of
449 * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
450 * the windows is gone, by wrapping the destroy call in an error
451 * handler. */
452
453 XSync(dpy, False);
454 oldXErrorHandler = XSetErrorHandler(noopErrorHandler);
455
456 LockDisplay(dpy);
457 GetReq(XF86DRIDestroyDrawable, req);
458 req->reqType = info->codes->major_opcode;
459 req->driReqType = X_XF86DRIDestroyDrawable;
460 req->screen = screen;
461 req->drawable = drawable;
462 UnlockDisplay(dpy);
463 SyncHandle();
464
465 XSetErrorHandler(oldXErrorHandler);
466
467 TRACE("DestroyDrawable... return True");
468 return True;
469 }
470
471 Bool
472 XF86DRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable,
473 unsigned int *index, unsigned int *stamp,
474 int *X, int *Y, int *W, int *H,
475 int *numClipRects, drm_clip_rect_t ** pClipRects,
476 int *backX, int *backY,
477 int *numBackClipRects,
478 drm_clip_rect_t ** pBackClipRects)
479 {
480 XExtDisplayInfo *info = find_display(dpy);
481 xXF86DRIGetDrawableInfoReply rep;
482 xXF86DRIGetDrawableInfoReq *req;
483 int total_rects;
484
485 TRACE("GetDrawableInfo...");
486 XF86DRICheckExtension(dpy, info, False);
487
488 LockDisplay(dpy);
489 GetReq(XF86DRIGetDrawableInfo, req);
490 req->reqType = info->codes->major_opcode;
491 req->driReqType = X_XF86DRIGetDrawableInfo;
492 req->screen = screen;
493 req->drawable = drawable;
494
495 if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) {
496 UnlockDisplay(dpy);
497 SyncHandle();
498 TRACE("GetDrawableInfo... return False");
499 return False;
500 }
501 *index = rep.drawableTableIndex;
502 *stamp = rep.drawableTableStamp;
503 *X = (int) rep.drawableX;
504 *Y = (int) rep.drawableY;
505 *W = (int) rep.drawableWidth;
506 *H = (int) rep.drawableHeight;
507 *numClipRects = rep.numClipRects;
508 total_rects = *numClipRects;
509
510 *backX = rep.backX;
511 *backY = rep.backY;
512 *numBackClipRects = rep.numBackClipRects;
513 total_rects += *numBackClipRects;
514
515 #if 0
516 /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
517 * backwards compatibility (Because of the >> 2 shift) but the fix
518 * enables multi-threaded apps to work.
519 */
520 if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
521 SIZEOF(xGenericReply) +
522 total_rects * sizeof(drm_clip_rect_t)) +
523 3) & ~3) >> 2)) {
524 _XEatData(dpy, rep.length);
525 UnlockDisplay(dpy);
526 SyncHandle();
527 TRACE("GetDrawableInfo... return False");
528 return False;
529 }
530 #endif
531
532 if (*numClipRects) {
533 int len = sizeof(drm_clip_rect_t) * (*numClipRects);
534
535 *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
536 if (*pClipRects)
537 _XRead(dpy, (char *) *pClipRects, len);
538 }
539 else {
540 *pClipRects = NULL;
541 }
542
543 if (*numBackClipRects) {
544 int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
545
546 *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
547 if (*pBackClipRects)
548 _XRead(dpy, (char *) *pBackClipRects, len);
549 }
550 else {
551 *pBackClipRects = NULL;
552 }
553
554 UnlockDisplay(dpy);
555 SyncHandle();
556 TRACE("GetDrawableInfo... return True");
557 return True;
558 }
559
560 Bool
561 XF86DRIGetDeviceInfo(Display * dpy, int screen, drm_handle_t * hFrameBuffer,
562 int *fbOrigin, int *fbSize, int *fbStride,
563 int *devPrivateSize, void **pDevPrivate)
564 {
565 XExtDisplayInfo *info = find_display(dpy);
566 xXF86DRIGetDeviceInfoReply rep;
567 xXF86DRIGetDeviceInfoReq *req;
568
569 TRACE("GetDeviceInfo...");
570 XF86DRICheckExtension(dpy, info, False);
571
572 LockDisplay(dpy);
573 GetReq(XF86DRIGetDeviceInfo, req);
574 req->reqType = info->codes->major_opcode;
575 req->driReqType = X_XF86DRIGetDeviceInfo;
576 req->screen = screen;
577 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
578 UnlockDisplay(dpy);
579 SyncHandle();
580 TRACE("GetDeviceInfo... return False");
581 return False;
582 }
583
584 *hFrameBuffer = rep.hFrameBufferLow;
585 if (sizeof(drm_handle_t) == 8) {
586 int shift = 32; /* var to prevent warning on next line */
587 *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
588 }
589
590 *fbOrigin = rep.framebufferOrigin;
591 *fbSize = rep.framebufferSize;
592 *fbStride = rep.framebufferStride;
593 *devPrivateSize = rep.devPrivateSize;
594
595 if (rep.length) {
596 if (!(*pDevPrivate = (void *) Xcalloc(rep.devPrivateSize, 1))) {
597 _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3));
598 UnlockDisplay(dpy);
599 SyncHandle();
600 TRACE("GetDeviceInfo... return False");
601 return False;
602 }
603 _XRead(dpy, (char *) *pDevPrivate, rep.devPrivateSize);
604 }
605 else {
606 *pDevPrivate = NULL;
607 }
608
609 UnlockDisplay(dpy);
610 SyncHandle();
611 TRACE("GetDeviceInfo... return True");
612 return True;
613 }
614
615 Bool
616 XF86DRIOpenFullScreen(Display * dpy, int screen, Drawable drawable)
617 {
618 /* This function and the underlying X protocol are deprecated.
619 */
620 (void) dpy;
621 (void) screen;
622 (void) drawable;
623 return False;
624 }
625
626 Bool
627 XF86DRICloseFullScreen(Display * dpy, int screen, Drawable drawable)
628 {
629 /* This function and the underlying X protocol are deprecated.
630 */
631 (void) dpy;
632 (void) screen;
633 (void) drawable;
634 return True;
635 }
636
637 #endif /* GLX_DIRECT_RENDERING */