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