Remove CVS keywords.
[mesa.git] / src / glx / x11 / 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__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
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 XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info,
87 xf86dri_extension_name,
88 &xf86dri_extension_hooks,
89 0, NULL)
90
91 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info)
92
93
94 /*****************************************************************************
95 * *
96 * public XFree86-DRI Extension routines *
97 * *
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
108 PUBLIC Bool XF86DRIQueryExtension (dpy, event_basep, error_basep)
109 Display *dpy;
110 int *event_basep, *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 } else {
121 TRACE("QueryExtension... return False");
122 return False;
123 }
124 }
125
126 PUBLIC Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
127 Display* dpy;
128 int* majorVersion;
129 int* minorVersion;
130 int* patchVersion;
131 {
132 XExtDisplayInfo *info = find_display (dpy);
133 xXF86DRIQueryVersionReply rep;
134 xXF86DRIQueryVersionReq *req;
135
136 TRACE("QueryVersion...");
137 XF86DRICheckExtension (dpy, info, False);
138
139 LockDisplay(dpy);
140 GetReq(XF86DRIQueryVersion, req);
141 req->reqType = info->codes->major_opcode;
142 req->driReqType = X_XF86DRIQueryVersion;
143 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
144 UnlockDisplay(dpy);
145 SyncHandle();
146 TRACE("QueryVersion... return False");
147 return False;
148 }
149 *majorVersion = rep.majorVersion;
150 *minorVersion = rep.minorVersion;
151 *patchVersion = rep.patchVersion;
152 UnlockDisplay(dpy);
153 SyncHandle();
154 TRACE("QueryVersion... return True");
155 return True;
156 }
157
158 PUBLIC Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable)
159 Display* dpy;
160 int screen;
161 Bool* isCapable;
162 {
163 XExtDisplayInfo *info = find_display (dpy);
164 xXF86DRIQueryDirectRenderingCapableReply rep;
165 xXF86DRIQueryDirectRenderingCapableReq *req;
166
167 TRACE("QueryDirectRenderingCapable...");
168 XF86DRICheckExtension (dpy, info, False);
169
170 LockDisplay(dpy);
171 GetReq(XF86DRIQueryDirectRenderingCapable, req);
172 req->reqType = info->codes->major_opcode;
173 req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
174 req->screen = screen;
175 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
176 UnlockDisplay(dpy);
177 SyncHandle();
178 TRACE("QueryDirectRenderingCapable... return False");
179 return False;
180 }
181 *isCapable = rep.isCapable;
182 UnlockDisplay(dpy);
183 SyncHandle();
184 TRACE("QueryDirectRenderingCapable... return True");
185 return True;
186 }
187
188 PUBLIC Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString)
189 Display* dpy;
190 int screen;
191 drm_handle_t * hSAREA;
192 char **busIdString;
193 {
194 XExtDisplayInfo *info = find_display (dpy);
195 xXF86DRIOpenConnectionReply rep;
196 xXF86DRIOpenConnectionReq *req;
197
198 TRACE("OpenConnection...");
199 XF86DRICheckExtension (dpy, info, False);
200
201 LockDisplay(dpy);
202 GetReq(XF86DRIOpenConnection, req);
203 req->reqType = info->codes->major_opcode;
204 req->driReqType = X_XF86DRIOpenConnection;
205 req->screen = screen;
206 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
207 UnlockDisplay(dpy);
208 SyncHandle();
209 TRACE("OpenConnection... return False");
210 return False;
211 }
212
213 *hSAREA = rep.hSAREALow;
214 if (sizeof(drm_handle_t) == 8) {
215 int shift = 32; /* var to prevent warning on next line */
216 *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
217 }
218
219 if (rep.length) {
220 if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
221 _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
222 UnlockDisplay(dpy);
223 SyncHandle();
224 TRACE("OpenConnection... return False");
225 return False;
226 }
227 _XReadPad(dpy, *busIdString, rep.busIdStringLength);
228 } else {
229 *busIdString = NULL;
230 }
231 UnlockDisplay(dpy);
232 SyncHandle();
233 TRACE("OpenConnection... return True");
234 return True;
235 }
236
237 PUBLIC Bool XF86DRIAuthConnection(dpy, screen, magic)
238 Display* dpy;
239 int screen;
240 drm_magic_t magic;
241 {
242 XExtDisplayInfo *info = find_display (dpy);
243 xXF86DRIAuthConnectionReq *req;
244 xXF86DRIAuthConnectionReply rep;
245
246 TRACE("AuthConnection...");
247 XF86DRICheckExtension (dpy, info, False);
248
249 LockDisplay(dpy);
250 GetReq(XF86DRIAuthConnection, req);
251 req->reqType = info->codes->major_opcode;
252 req->driReqType = X_XF86DRIAuthConnection;
253 req->screen = screen;
254 req->magic = magic;
255 rep.authenticated = 0;
256 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
257 UnlockDisplay(dpy);
258 SyncHandle();
259 TRACE("AuthConnection... return False");
260 return False;
261 }
262 UnlockDisplay(dpy);
263 SyncHandle();
264 TRACE("AuthConnection... return True");
265 return True;
266 }
267
268 PUBLIC Bool XF86DRICloseConnection(dpy, screen)
269 Display* dpy;
270 int screen;
271 {
272 XExtDisplayInfo *info = find_display (dpy);
273 xXF86DRICloseConnectionReq *req;
274
275 TRACE("CloseConnection...");
276
277 XF86DRICheckExtension (dpy, info, False);
278
279 LockDisplay(dpy);
280 GetReq(XF86DRICloseConnection, req);
281 req->reqType = info->codes->major_opcode;
282 req->driReqType = X_XF86DRICloseConnection;
283 req->screen = screen;
284 UnlockDisplay(dpy);
285 SyncHandle();
286 TRACE("CloseConnection... return True");
287 return True;
288 }
289
290 PUBLIC Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
291 ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
292 Display* dpy;
293 int screen;
294 int* ddxDriverMajorVersion;
295 int* ddxDriverMinorVersion;
296 int* ddxDriverPatchVersion;
297 char** clientDriverName;
298 {
299 XExtDisplayInfo *info = find_display (dpy);
300 xXF86DRIGetClientDriverNameReply rep;
301 xXF86DRIGetClientDriverNameReq *req;
302
303 TRACE("GetClientDriverName...");
304 XF86DRICheckExtension (dpy, info, False);
305
306 LockDisplay(dpy);
307 GetReq(XF86DRIGetClientDriverName, req);
308 req->reqType = info->codes->major_opcode;
309 req->driReqType = X_XF86DRIGetClientDriverName;
310 req->screen = screen;
311 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
312 UnlockDisplay(dpy);
313 SyncHandle();
314 TRACE("GetClientDriverName... return False");
315 return False;
316 }
317
318 *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
319 *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
320 *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
321
322 if (rep.length) {
323 if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
324 _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
325 UnlockDisplay(dpy);
326 SyncHandle();
327 TRACE("GetClientDriverName... return False");
328 return False;
329 }
330 _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
331 } else {
332 *clientDriverName = NULL;
333 }
334 UnlockDisplay(dpy);
335 SyncHandle();
336 TRACE("GetClientDriverName... return True");
337 return True;
338 }
339
340 PUBLIC Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context,
341 hHWContext)
342 Display* dpy;
343 int screen;
344 int configID;
345 XID* context;
346 drm_context_t * hHWContext;
347 {
348 XExtDisplayInfo *info = find_display (dpy);
349 xXF86DRICreateContextReply rep;
350 xXF86DRICreateContextReq *req;
351
352 TRACE("CreateContext...");
353 XF86DRICheckExtension (dpy, info, False);
354
355 LockDisplay(dpy);
356 GetReq(XF86DRICreateContext, req);
357 req->reqType = info->codes->major_opcode;
358 req->driReqType = X_XF86DRICreateContext;
359 req->visual = configID;
360 req->screen = screen;
361 *context = XAllocID(dpy);
362 req->context = *context;
363 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
364 UnlockDisplay(dpy);
365 SyncHandle();
366 TRACE("CreateContext... return False");
367 return False;
368 }
369 *hHWContext = rep.hHWContext;
370 UnlockDisplay(dpy);
371 SyncHandle();
372 TRACE("CreateContext... return True");
373 return True;
374 }
375
376 PUBLIC Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext)
377 Display* dpy;
378 int screen;
379 Visual* visual;
380 XID* context;
381 drm_context_t * hHWContext;
382 {
383 return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid,
384 context, hHWContext );
385 }
386
387 PUBLIC Bool XF86DRIDestroyContext(Display *dpy, int screen,
388 XID context )
389 {
390 XExtDisplayInfo *info = find_display (dpy);
391 xXF86DRIDestroyContextReq *req;
392
393 TRACE("DestroyContext...");
394 XF86DRICheckExtension (dpy, info, False);
395
396 LockDisplay(dpy);
397 GetReq(XF86DRIDestroyContext, req);
398 req->reqType = info->codes->major_opcode;
399 req->driReqType = X_XF86DRIDestroyContext;
400 req->screen = screen;
401 req->context = context;
402 UnlockDisplay(dpy);
403 SyncHandle();
404 TRACE("DestroyContext... return True");
405 return True;
406 }
407
408 PUBLIC Bool XF86DRICreateDrawable(Display *dpy, int screen,
409 XID drawable, drm_drawable_t * hHWDrawable )
410 {
411 XExtDisplayInfo *info = find_display (dpy);
412 xXF86DRICreateDrawableReply rep;
413 xXF86DRICreateDrawableReq *req;
414
415 TRACE("CreateDrawable...");
416 XF86DRICheckExtension (dpy, info, False);
417
418 LockDisplay(dpy);
419 GetReq(XF86DRICreateDrawable, req);
420 req->reqType = info->codes->major_opcode;
421 req->driReqType = X_XF86DRICreateDrawable;
422 req->screen = screen;
423 req->drawable = drawable;
424 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
425 UnlockDisplay(dpy);
426 SyncHandle();
427 TRACE("CreateDrawable... return False");
428 return False;
429 }
430 *hHWDrawable = rep.hHWDrawable;
431 UnlockDisplay(dpy);
432 SyncHandle();
433 TRACE("CreateDrawable... return True");
434 return True;
435 }
436
437 static int noopErrorHandler(Display *dpy, XErrorEvent *xerr)
438 {
439 return 0;
440 }
441
442 PUBLIC Bool XF86DRIDestroyDrawable(Display *dpy, int screen,
443 XID drawable )
444 {
445 XExtDisplayInfo *info = find_display (dpy);
446 xXF86DRIDestroyDrawableReq *req;
447 int (*oldXErrorHandler)(Display *, XErrorEvent *);
448
449 TRACE("DestroyDrawable...");
450 XF86DRICheckExtension (dpy, info, False);
451
452 /* This is called from the DRI driver, which used call it like this
453 *
454 * if (windowExists(drawable))
455 * destroyDrawable(drawable);
456 *
457 * which is a textbook race condition - the window may disappear
458 * from the server between checking for its existance and
459 * destroying it. Instead we change the semantics of
460 * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
461 * the windows is gone, by wrapping the destroy call in an error
462 * handler. */
463
464 XSync(dpy, False);
465 oldXErrorHandler = XSetErrorHandler(noopErrorHandler);
466
467 LockDisplay(dpy);
468 GetReq(XF86DRIDestroyDrawable, req);
469 req->reqType = info->codes->major_opcode;
470 req->driReqType = X_XF86DRIDestroyDrawable;
471 req->screen = screen;
472 req->drawable = drawable;
473 UnlockDisplay(dpy);
474 SyncHandle();
475
476 XSetErrorHandler(oldXErrorHandler);
477
478 TRACE("DestroyDrawable... return True");
479 return True;
480 }
481
482 PUBLIC Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
483 unsigned int* index, unsigned int* stamp,
484 int* X, int* Y, int* W, int* H,
485 int* numClipRects, drm_clip_rect_t ** pClipRects,
486 int* backX, int* backY,
487 int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
488 {
489 XExtDisplayInfo *info = find_display (dpy);
490 xXF86DRIGetDrawableInfoReply rep;
491 xXF86DRIGetDrawableInfoReq *req;
492 int total_rects;
493
494 TRACE("GetDrawableInfo...");
495 XF86DRICheckExtension (dpy, info, False);
496
497 LockDisplay(dpy);
498 GetReq(XF86DRIGetDrawableInfo, req);
499 req->reqType = info->codes->major_opcode;
500 req->driReqType = X_XF86DRIGetDrawableInfo;
501 req->screen = screen;
502 req->drawable = drawable;
503
504 if (!_XReply(dpy, (xReply *)&rep, 1, xFalse))
505 {
506 UnlockDisplay(dpy);
507 SyncHandle();
508 TRACE("GetDrawableInfo... return False");
509 return False;
510 }
511 *index = rep.drawableTableIndex;
512 *stamp = rep.drawableTableStamp;
513 *X = (int)rep.drawableX;
514 *Y = (int)rep.drawableY;
515 *W = (int)rep.drawableWidth;
516 *H = (int)rep.drawableHeight;
517 *numClipRects = rep.numClipRects;
518 total_rects = *numClipRects;
519
520 *backX = rep.backX;
521 *backY = rep.backY;
522 *numBackClipRects = rep.numBackClipRects;
523 total_rects += *numBackClipRects;
524
525 #if 0
526 /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
527 * backwards compatibility (Because of the >> 2 shift) but the fix
528 * enables multi-threaded apps to work.
529 */
530 if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
531 SIZEOF(xGenericReply) +
532 total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
533 _XEatData(dpy, rep.length);
534 UnlockDisplay(dpy);
535 SyncHandle();
536 TRACE("GetDrawableInfo... return False");
537 return False;
538 }
539 #endif
540
541 if (*numClipRects) {
542 int len = sizeof(drm_clip_rect_t) * (*numClipRects);
543
544 *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
545 if (*pClipRects)
546 _XRead(dpy, (char*)*pClipRects, len);
547 } else {
548 *pClipRects = NULL;
549 }
550
551 if (*numBackClipRects) {
552 int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
553
554 *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
555 if (*pBackClipRects)
556 _XRead(dpy, (char*)*pBackClipRects, len);
557 } else {
558 *pBackClipRects = NULL;
559 }
560
561 UnlockDisplay(dpy);
562 SyncHandle();
563 TRACE("GetDrawableInfo... return True");
564 return True;
565 }
566
567 PUBLIC Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer,
568 fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
569 Display* dpy;
570 int screen;
571 drm_handle_t * hFrameBuffer;
572 int* fbOrigin;
573 int* fbSize;
574 int* fbStride;
575 int* devPrivateSize;
576 void** pDevPrivate;
577 {
578 XExtDisplayInfo *info = find_display (dpy);
579 xXF86DRIGetDeviceInfoReply rep;
580 xXF86DRIGetDeviceInfoReq *req;
581
582 TRACE("GetDeviceInfo...");
583 XF86DRICheckExtension (dpy, info, False);
584
585 LockDisplay(dpy);
586 GetReq(XF86DRIGetDeviceInfo, req);
587 req->reqType = info->codes->major_opcode;
588 req->driReqType = X_XF86DRIGetDeviceInfo;
589 req->screen = screen;
590 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
591 UnlockDisplay(dpy);
592 SyncHandle();
593 TRACE("GetDeviceInfo... return False");
594 return False;
595 }
596
597 *hFrameBuffer = rep.hFrameBufferLow;
598 if (sizeof(drm_handle_t) == 8) {
599 int shift = 32; /* var to prevent warning on next line */
600 *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
601 }
602
603 *fbOrigin = rep.framebufferOrigin;
604 *fbSize = rep.framebufferSize;
605 *fbStride = rep.framebufferStride;
606 *devPrivateSize = rep.devPrivateSize;
607
608 if (rep.length) {
609 if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
610 _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
611 UnlockDisplay(dpy);
612 SyncHandle();
613 TRACE("GetDeviceInfo... return False");
614 return False;
615 }
616 _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
617 } else {
618 *pDevPrivate = NULL;
619 }
620
621 UnlockDisplay(dpy);
622 SyncHandle();
623 TRACE("GetDeviceInfo... return True");
624 return True;
625 }
626
627 PUBLIC Bool XF86DRIOpenFullScreen(dpy, screen, drawable)
628 Display* dpy;
629 int screen;
630 Drawable drawable;
631 {
632 /* This function and the underlying X protocol are deprecated.
633 */
634 (void) dpy;
635 (void) screen;
636 (void) drawable;
637 return False;
638 }
639
640 PUBLIC Bool XF86DRICloseFullScreen(dpy, screen, drawable)
641 Display* dpy;
642 int screen;
643 Drawable drawable;
644 {
645 /* This function and the underlying X protocol are deprecated.
646 */
647 (void) dpy;
648 (void) screen;
649 (void) drawable;
650 return True;
651 }
652
653 #endif /* GLX_DIRECT_RENDERING */