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