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