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