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