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