1 /**************************************************************************
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 Copyright 2000 VA Linux Systems, Inc.
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:
15 The above copyright notice and this permission notice (including the
16 next paragraph) shall be included in all copies or substantial portions
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.
27 **************************************************************************/
31 * Jens Owen <jens@tungstengraphics.com>
32 * Rickard E. (Rik) Faith <faith@valinux.com>
36 #ifdef HAVE_XORG_CONFIG_H
37 #include <xorg-config.h>
45 #include <sys/ioctl.h>
49 #include <X11/Xproto.h>
52 #include "dixstruct.h"
53 #include "extnsionst.h"
55 #include "colormapst.h"
56 #include "cursorstr.h"
57 #include "scrnintstr.h"
58 #include "windowstr.h"
60 #define _XF86DRI_SERVER_
61 #include <X11/dri/xf86driproto.h>
66 #include "dristruct.h"
68 #include "mipointer.h"
69 #include "xf86_OSproc.h"
71 #include "xf86VGAarbiter.h"
72 #include "xf86Extensions.h"
74 static int DRIEntPrivIndex
= -1;
75 static DevPrivateKeyRec DRIScreenPrivKeyRec
;
77 #define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
78 static DevPrivateKeyRec DRIWindowPrivKeyRec
;
80 #define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
81 static unsigned long DRIGeneration
= 0;
82 static unsigned int DRIDrawableValidationStamp
= 0;
84 static RESTYPE DRIDrawablePrivResType
;
85 static RESTYPE DRIContextPrivResType
;
86 static void DRIDestroyDummyContext(ScreenPtr pScreen
, Bool hasCtxPriv
);
88 drmServerInfo DRIDRMServerInfo
;
90 /* Wrapper just like xf86DrvMsg, but
91 without the verbosity level checking.
92 This will make it easy to turn off some
93 messages later, based on verbosity
97 * Since we're already referencing things from the XFree86 common layer in
98 * this file, we'd might as well just call xf86VDrvMsgVerb, and have
99 * consistent message formatting. The verbosity of these messages can be
100 * easily changed here.
102 #define DRI_MSG_VERBOSITY 1
104 DRIDrvMsg(int scrnIndex
, MessageType type
, const char *format
, ...)
108 va_start(ap
, format
);
109 xf86VDrvMsgVerb(scrnIndex
, type
, DRI_MSG_VERBOSITY
, format
, ap
);
114 DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv
)
116 if (pDRIEntPriv
->pLSAREA
!= NULL
) {
117 drmUnmap(pDRIEntPriv
->pLSAREA
, pDRIEntPriv
->sAreaSize
);
118 pDRIEntPriv
->pLSAREA
= NULL
;
120 if (pDRIEntPriv
->hLSAREA
!= 0) {
121 drmRmMap(pDRIEntPriv
->drmFD
, pDRIEntPriv
->hLSAREA
);
123 if (pDRIEntPriv
->drmFD
>= 0) {
124 drmClose(pDRIEntPriv
->drmFD
);
125 pDRIEntPriv
->drmFD
= 0;
130 DRIMasterFD(ScrnInfoPtr pScrn
)
132 return DRI_ENT_PRIV(pScrn
)->drmFD
;
136 DRIMasterSareaPointer(ScrnInfoPtr pScrn
)
138 return DRI_ENT_PRIV(pScrn
)->pLSAREA
;
142 DRIMasterSareaHandle(ScrnInfoPtr pScrn
)
144 return DRI_ENT_PRIV(pScrn
)->hLSAREA
;
148 DRIOpenDRMMaster(ScrnInfoPtr pScrn
,
149 unsigned long sAreaSize
,
150 const char *busID
, const char *drmDriverName
)
152 drmSetVersion saveSv
, sv
;
153 Bool drmWasAvailable
;
154 DRIEntPrivPtr pDRIEntPriv
;
156 drmVersionPtr drmlibv
;
157 int drmlibmajor
, drmlibminor
;
158 const char *openBusID
;
162 if (DRIEntPrivIndex
== -1)
163 DRIEntPrivIndex
= xf86AllocateEntityPrivateIndex();
165 pDRIEntPriv
= DRI_ENT_PRIV(pScrn
);
167 if (pDRIEntPriv
&& pDRIEntPriv
->drmFD
!= -1)
170 drmWasAvailable
= drmAvailable();
172 memset(&tmp
, 0, sizeof(tmp
));
174 /* Check the DRM lib version.
175 * drmGetLibVersion was not supported in version 1.0, so check for
176 * symbol first to avoid possible crash or hang.
181 if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
182 drmlibv
= drmGetLibVersion(-1);
183 if (drmlibv
!= NULL
) {
184 drmlibmajor
= drmlibv
->version_major
;
185 drmlibminor
= drmlibv
->version_minor
;
186 drmFreeVersion(drmlibv
);
190 /* Check if the libdrm can handle falling back to loading based on name
191 * if a busid string is passed.
193 openBusID
= (drmlibmajor
== 1 && drmlibminor
>= 2) ? busID
: NULL
;
198 sv
.drm_dd_major
= -1;
203 tmp
.drmFD
= drmOpen(drmDriverName
, openBusID
);
206 DRIDrvMsg(-1, X_ERROR
, "[drm] drmOpen failed.\n");
210 err
= drmSetInterfaceVersion(tmp
.drmFD
, &sv
);
221 if (tmp
.drmFD
<= 0) {
222 DRIDrvMsg(-1, X_ERROR
, "[drm] DRM was busy with another master.\n");
226 if (!drmWasAvailable
) {
227 DRIDrvMsg(-1, X_INFO
,
228 "[drm] loaded kernel module for \"%s\" driver.\n",
237 DRIDrvMsg(-1, X_INFO
, "[drm] DRM interface version %d.%d\n",
238 sv
.drm_di_major
, sv
.drm_di_minor
);
240 if (sv
.drm_di_major
== 1 && sv
.drm_di_minor
>= 1)
243 err
= drmSetBusid(tmp
.drmFD
, busID
);
246 DRIDrvMsg(-1, X_ERROR
, "[drm] Could not set DRM device bus ID.\n");
251 * Create a lock-containing sarea.
254 if (drmAddMap(tmp
.drmFD
, 0, sAreaSize
, DRM_SHM
,
255 DRM_CONTAINS_LOCK
, &tmp
.hLSAREA
) < 0) {
256 DRIDrvMsg(-1, X_INFO
, "[drm] Could not create SAREA for DRM lock.\n");
261 if (drmMap(tmp
.drmFD
, tmp
.hLSAREA
, sAreaSize
,
262 (drmAddressPtr
) (&tmp
.pLSAREA
)) < 0) {
263 DRIDrvMsg(-1, X_INFO
, "[drm] Mapping SAREA for DRM lock failed.\n");
268 memset(tmp
.pLSAREA
, 0, sAreaSize
);
271 * Reserved contexts are handled by the first opened screen.
277 pDRIEntPriv
= xnfcalloc(sizeof(*pDRIEntPriv
), 1);
280 DRIDrvMsg(-1, X_INFO
, "[drm] Failed to allocate memory for "
285 xf86GetEntityPrivate((pScrn
)->entityList
[0], DRIEntPrivIndex
)->ptr
=
288 DRIDrvMsg(-1, X_INFO
, "[drm] DRM open master succeeded.\n");
293 DRIOpenDRMCleanup(&tmp
);
298 DRIClipNotifyAllDrawables(ScreenPtr pScreen
);
301 dri_crtc_notify(ScreenPtr pScreen
)
303 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
305 DRIClipNotifyAllDrawables(pScreen
);
306 xf86_unwrap_crtc_notify(pScreen
, pDRIPriv
->xf86_crtc_notify
);
307 xf86_crtc_notify(pScreen
);
308 pDRIPriv
->xf86_crtc_notify
=
309 xf86_wrap_crtc_notify(pScreen
, dri_crtc_notify
);
313 DRIScreenInit(ScreenPtr pScreen
, DRIInfoPtr pDRIInfo
, int *pDRMFD
)
315 DRIScreenPrivPtr pDRIPriv
;
316 drm_context_t
*reserved
;
319 DRIEntPrivPtr pDRIEntPriv
;
320 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
321 DRIContextFlags flags
= 0;
322 DRIContextPrivPtr pDRIContextPriv
;
323 static Bool drm_server_inited
;
325 /* If the DRI extension is disabled, do not initialize the DRI */
326 if (noXFree86DRIExtension
) {
327 DRIDrvMsg(pScreen
->myNum
, X_WARNING
,
328 "Direct rendering has been disabled.\n");
332 if (!xf86VGAarbiterAllowDRI(pScreen
)) {
333 DRIDrvMsg(pScreen
->myNum
, X_WARNING
,
334 "Direct rendering is not supported when VGA arb is necessary for the device\n");
340 * If Xinerama is on, don't allow DRI to initialise. It won't be usable
343 if (!noPanoramiXExtension
) {
344 DRIDrvMsg(pScreen
->myNum
, X_WARNING
,
345 "Direct rendering is not supported when Xinerama is enabled\n");
349 if (drm_server_inited
== FALSE
) {
350 drmSetServerInfo(&DRIDRMServerInfo
);
351 drm_server_inited
= TRUE
;
354 if (!DRIOpenDRMMaster(pScrn
, pDRIInfo
->SAREASize
,
355 pDRIInfo
->busIdString
, pDRIInfo
->drmDriverName
))
358 pDRIEntPriv
= DRI_ENT_PRIV(pScrn
);
360 if (DRIGeneration
!= serverGeneration
)
361 DRIGeneration
= serverGeneration
;
363 if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec
, PRIVATE_SCREEN
, 0))
365 if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec
, PRIVATE_WINDOW
, 0))
368 pDRIPriv
= (DRIScreenPrivPtr
) calloc(1, sizeof(DRIScreenPrivRec
));
370 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, NULL
);
374 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, pDRIPriv
);
375 pDRIPriv
->drmFD
= pDRIEntPriv
->drmFD
;
376 pDRIPriv
->directRenderingSupport
= TRUE
;
377 pDRIPriv
->pDriverInfo
= pDRIInfo
;
378 pDRIPriv
->nrWindows
= 0;
379 pDRIPriv
->nrWindowsVisible
= 0;
380 pDRIPriv
->fullscreen
= NULL
;
382 pDRIPriv
->createDummyCtx
= pDRIInfo
->createDummyCtx
;
383 pDRIPriv
->createDummyCtxPriv
= pDRIInfo
->createDummyCtxPriv
;
385 pDRIPriv
->grabbedDRILock
= FALSE
;
386 pDRIPriv
->drmSIGIOHandlerInstalled
= FALSE
;
387 *pDRMFD
= pDRIPriv
->drmFD
;
389 if (pDRIEntPriv
->sAreaGrabbed
|| pDRIInfo
->allocSarea
) {
391 if (drmAddMap(pDRIPriv
->drmFD
,
393 pDRIPriv
->pDriverInfo
->SAREASize
,
394 DRM_SHM
, 0, &pDRIPriv
->hSAREA
) < 0) {
395 pDRIPriv
->directRenderingSupport
= FALSE
;
396 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, NULL
);
397 drmClose(pDRIPriv
->drmFD
);
398 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[drm] drmAddMap failed\n");
401 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
402 "[drm] added %d byte SAREA at %p\n",
403 pDRIPriv
->pDriverInfo
->SAREASize
, pDRIPriv
->hSAREA
);
405 /* Backwards compat. */
406 if (drmMap(pDRIPriv
->drmFD
,
408 pDRIPriv
->pDriverInfo
->SAREASize
,
409 (drmAddressPtr
) (&pDRIPriv
->pSAREA
)) < 0) {
410 pDRIPriv
->directRenderingSupport
= FALSE
;
411 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, NULL
);
412 drmClose(pDRIPriv
->drmFD
);
413 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[drm] drmMap failed\n");
416 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[drm] mapped SAREA %p to %p\n",
417 pDRIPriv
->hSAREA
, pDRIPriv
->pSAREA
);
418 memset(pDRIPriv
->pSAREA
, 0, pDRIPriv
->pDriverInfo
->SAREASize
);
421 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Using the DRM lock "
422 "SAREA also for drawables.\n");
423 pDRIPriv
->hSAREA
= pDRIEntPriv
->hLSAREA
;
424 pDRIPriv
->pSAREA
= (XF86DRISAREAPtr
) pDRIEntPriv
->pLSAREA
;
425 pDRIEntPriv
->sAreaGrabbed
= TRUE
;
428 pDRIPriv
->hLSAREA
= pDRIEntPriv
->hLSAREA
;
429 pDRIPriv
->pLSAREA
= pDRIEntPriv
->pLSAREA
;
431 if (!pDRIPriv
->pDriverInfo
->dontMapFrameBuffer
) {
432 if (drmAddMap(pDRIPriv
->drmFD
,
433 (uintptr_t) pDRIPriv
->pDriverInfo
->
434 frameBufferPhysicalAddress
,
435 pDRIPriv
->pDriverInfo
->frameBufferSize
, DRM_FRAME_BUFFER
,
436 0, &pDRIPriv
->pDriverInfo
->hFrameBuffer
) < 0) {
437 pDRIPriv
->directRenderingSupport
= FALSE
;
438 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, NULL
);
439 drmUnmap(pDRIPriv
->pSAREA
, pDRIPriv
->pDriverInfo
->SAREASize
);
440 drmClose(pDRIPriv
->drmFD
);
441 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[drm] drmAddMap failed\n");
444 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[drm] framebuffer handle = %p\n",
445 pDRIPriv
->pDriverInfo
->hFrameBuffer
);
448 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
449 "[drm] framebuffer mapped by ddx driver\n");
452 if (pDRIEntPriv
->resOwner
== NULL
) {
453 pDRIEntPriv
->resOwner
= pScreen
;
455 /* Add tags for reserved contexts */
456 if ((reserved
= drmGetReservedContextList(pDRIPriv
->drmFD
,
461 for (i
= 0; i
< reserved_count
; i
++) {
462 tag
= DRICreateContextPrivFromHandle(pScreen
,
464 DRI_CONTEXT_RESERVED
);
465 drmAddContextTag(pDRIPriv
->drmFD
, reserved
[i
], tag
);
467 drmFreeReservedContextList(reserved
);
468 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
469 "[drm] added %d reserved context%s for kernel\n",
470 reserved_count
, reserved_count
> 1 ? "s" : "");
474 /* validate max drawable table entry set by driver */
475 if ((pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
<= 0) ||
476 (pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
> SAREA_MAX_DRAWABLES
)) {
477 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
478 "Invalid max drawable table size set by driver: %d\n",
479 pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
);
482 /* Initialize drawable tables (screen private and SAREA) */
483 for (i
= 0; i
< pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
; i
++) {
484 pDRIPriv
->DRIDrawables
[i
] = NULL
;
485 pDRIPriv
->pSAREA
->drawableTable
[i
].stamp
= 0;
486 pDRIPriv
->pSAREA
->drawableTable
[i
].flags
= 0;
489 pDRIPriv
->pLockRefCount
= &pDRIEntPriv
->lockRefCount
;
490 pDRIPriv
->pLockingContext
= &pDRIEntPriv
->lockingContext
;
492 if (!pDRIEntPriv
->keepFDOpen
)
493 pDRIEntPriv
->keepFDOpen
= pDRIInfo
->keepFDOpen
;
495 pDRIEntPriv
->refCount
++;
497 /* Set up flags for DRICreateContextPriv */
498 switch (pDRIInfo
->driverSwapMethod
) {
499 case DRI_KERNEL_SWAP
:
500 flags
= DRI_CONTEXT_2DONLY
;
502 case DRI_HIDE_X_CONTEXT
:
503 flags
= DRI_CONTEXT_PRESERVED
;
507 if (!(pDRIContextPriv
= DRICreateContextPriv(pScreen
,
508 &pDRIPriv
->myContext
,
510 DRIDrvMsg(pScreen
->myNum
, X_ERROR
, "failed to create server context\n");
513 pDRIPriv
->myContextPriv
= pDRIContextPriv
;
515 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
516 "X context handle = %p\n", pDRIPriv
->myContext
);
518 /* Now that we have created the X server's context, we can grab the
519 * hardware lock for the X server.
522 pDRIPriv
->grabbedDRILock
= TRUE
;
524 /* pointers so that we can prevent memory leaks later */
525 pDRIPriv
->hiddenContextStore
= NULL
;
526 pDRIPriv
->partial3DContextStore
= NULL
;
528 switch (pDRIInfo
->driverSwapMethod
) {
529 case DRI_HIDE_X_CONTEXT
:
530 /* Server will handle 3D swaps, and hide 2D swaps from kernel.
531 * Register server context as a preserved context.
534 /* allocate memory for hidden context store */
535 pDRIPriv
->hiddenContextStore
536 = (void *) calloc(1, pDRIInfo
->contextSize
);
537 if (!pDRIPriv
->hiddenContextStore
) {
538 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
539 "failed to allocate hidden context\n");
540 DRIDestroyContextPriv(pDRIContextPriv
);
544 /* allocate memory for partial 3D context store */
545 pDRIPriv
->partial3DContextStore
546 = (void *) calloc(1, pDRIInfo
->contextSize
);
547 if (!pDRIPriv
->partial3DContextStore
) {
548 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
549 "[DRI] failed to allocate partial 3D context\n");
550 free(pDRIPriv
->hiddenContextStore
);
551 DRIDestroyContextPriv(pDRIContextPriv
);
555 /* save initial context store */
556 if (pDRIInfo
->SwapContext
) {
557 (*pDRIInfo
->SwapContext
) (pScreen
,
560 pDRIPriv
->hiddenContextStore
,
561 DRI_NO_CONTEXT
, NULL
);
565 case DRI_SERVER_SWAP
:
566 /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT
567 * setup signal handler for receiving swap requests from kernel
569 if (!(pDRIPriv
->drmSIGIOHandlerInstalled
=
570 drmInstallSIGIOHandler(pDRIPriv
->drmFD
, DRISwapContext
))) {
571 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
572 "[drm] failed to setup DRM signal handler\n");
573 free(pDRIPriv
->hiddenContextStore
);
574 free(pDRIPriv
->partial3DContextStore
);
575 DRIDestroyContextPriv(pDRIContextPriv
);
579 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
580 "[drm] installed DRM signal handler\n");
591 DRIFinishScreenInit(ScreenPtr pScreen
)
593 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
594 DRIInfoPtr pDRIInfo
= pDRIPriv
->pDriverInfo
;
596 /* Wrap DRI support */
597 if (pDRIInfo
->wrap
.ValidateTree
) {
598 pDRIPriv
->wrap
.ValidateTree
= pScreen
->ValidateTree
;
599 pScreen
->ValidateTree
= pDRIInfo
->wrap
.ValidateTree
;
601 if (pDRIInfo
->wrap
.PostValidateTree
) {
602 pDRIPriv
->wrap
.PostValidateTree
= pScreen
->PostValidateTree
;
603 pScreen
->PostValidateTree
= pDRIInfo
->wrap
.PostValidateTree
;
605 if (pDRIInfo
->wrap
.WindowExposures
) {
606 pDRIPriv
->wrap
.WindowExposures
= pScreen
->WindowExposures
;
607 pScreen
->WindowExposures
= pDRIInfo
->wrap
.WindowExposures
;
610 pDRIPriv
->DestroyWindow
= pScreen
->DestroyWindow
;
611 pScreen
->DestroyWindow
= DRIDestroyWindow
;
613 pDRIPriv
->xf86_crtc_notify
= xf86_wrap_crtc_notify(pScreen
,
616 if (pDRIInfo
->wrap
.CopyWindow
) {
617 pDRIPriv
->wrap
.CopyWindow
= pScreen
->CopyWindow
;
618 pScreen
->CopyWindow
= pDRIInfo
->wrap
.CopyWindow
;
620 if (pDRIInfo
->wrap
.ClipNotify
) {
621 pDRIPriv
->wrap
.ClipNotify
= pScreen
->ClipNotify
;
622 pScreen
->ClipNotify
= pDRIInfo
->wrap
.ClipNotify
;
624 if (pDRIInfo
->wrap
.AdjustFrame
) {
625 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
627 pDRIPriv
->wrap
.AdjustFrame
= pScrn
->AdjustFrame
;
628 pScrn
->AdjustFrame
= pDRIInfo
->wrap
.AdjustFrame
;
630 pDRIPriv
->wrapped
= TRUE
;
632 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[DRI] installation complete\n");
638 DRICloseScreen(ScreenPtr pScreen
)
640 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
642 drm_context_t
*reserved
;
644 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
645 DRIEntPrivPtr pDRIEntPriv
= DRI_ENT_PRIV(pScrn
);
650 pDRIInfo
= pDRIPriv
->pDriverInfo
;
652 if (pDRIPriv
->wrapped
) {
653 /* Unwrap DRI Functions */
654 if (pDRIInfo
->wrap
.ValidateTree
) {
655 pScreen
->ValidateTree
= pDRIPriv
->wrap
.ValidateTree
;
656 pDRIPriv
->wrap
.ValidateTree
= NULL
;
658 if (pDRIInfo
->wrap
.PostValidateTree
) {
659 pScreen
->PostValidateTree
= pDRIPriv
->wrap
.PostValidateTree
;
660 pDRIPriv
->wrap
.PostValidateTree
= NULL
;
662 if (pDRIInfo
->wrap
.WindowExposures
) {
663 pScreen
->WindowExposures
= pDRIPriv
->wrap
.WindowExposures
;
664 pDRIPriv
->wrap
.WindowExposures
= NULL
;
666 if (pDRIPriv
->DestroyWindow
) {
667 pScreen
->DestroyWindow
= pDRIPriv
->DestroyWindow
;
668 pDRIPriv
->DestroyWindow
= NULL
;
671 xf86_unwrap_crtc_notify(pScreen
, pDRIPriv
->xf86_crtc_notify
);
673 if (pDRIInfo
->wrap
.CopyWindow
) {
674 pScreen
->CopyWindow
= pDRIPriv
->wrap
.CopyWindow
;
675 pDRIPriv
->wrap
.CopyWindow
= NULL
;
677 if (pDRIInfo
->wrap
.ClipNotify
) {
678 pScreen
->ClipNotify
= pDRIPriv
->wrap
.ClipNotify
;
679 pDRIPriv
->wrap
.ClipNotify
= NULL
;
681 if (pDRIInfo
->wrap
.AdjustFrame
) {
682 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
684 pScrn
->AdjustFrame
= pDRIPriv
->wrap
.AdjustFrame
;
685 pDRIPriv
->wrap
.AdjustFrame
= NULL
;
688 pDRIPriv
->wrapped
= FALSE
;
691 if (pDRIPriv
->drmSIGIOHandlerInstalled
) {
692 if (!drmRemoveSIGIOHandler(pDRIPriv
->drmFD
)) {
693 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
694 "[drm] failed to remove DRM signal handler\n");
698 if (pDRIPriv
->dummyCtxPriv
&& pDRIPriv
->createDummyCtx
) {
699 DRIDestroyDummyContext(pScreen
, pDRIPriv
->createDummyCtxPriv
);
702 if (!DRIDestroyContextPriv(pDRIPriv
->myContextPriv
)) {
703 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
704 "failed to destroy server context\n");
707 /* Remove tags for reserved contexts */
708 if (pDRIEntPriv
->resOwner
== pScreen
) {
709 pDRIEntPriv
->resOwner
= NULL
;
711 if ((reserved
= drmGetReservedContextList(pDRIPriv
->drmFD
,
715 for (i
= 0; i
< reserved_count
; i
++) {
716 DRIDestroyContextPriv(drmGetContextTag(pDRIPriv
->drmFD
,
719 drmFreeReservedContextList(reserved
);
720 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
721 "[drm] removed %d reserved context%s for kernel\n",
722 reserved_count
, reserved_count
> 1 ? "s" : "");
726 /* Make sure signals get unblocked etc. */
727 drmUnlock(pDRIPriv
->drmFD
, pDRIPriv
->myContext
);
728 pDRIPriv
->pLockRefCount
= NULL
;
729 closeMaster
= (--pDRIEntPriv
->refCount
== 0) &&
730 !pDRIEntPriv
->keepFDOpen
;
731 if (closeMaster
|| pDRIPriv
->hSAREA
!= pDRIEntPriv
->hLSAREA
) {
732 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
733 "[drm] unmapping %d bytes of SAREA %p at %p\n",
734 pDRIInfo
->SAREASize
, pDRIPriv
->hSAREA
, pDRIPriv
->pSAREA
);
735 if (drmUnmap(pDRIPriv
->pSAREA
, pDRIInfo
->SAREASize
)) {
736 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
737 "[drm] unable to unmap %d bytes"
738 " of SAREA %p at %p\n",
740 pDRIPriv
->hSAREA
, pDRIPriv
->pSAREA
);
744 pDRIEntPriv
->sAreaGrabbed
= FALSE
;
747 if (closeMaster
|| (pDRIEntPriv
->drmFD
!= pDRIPriv
->drmFD
)) {
748 drmClose(pDRIPriv
->drmFD
);
749 if (pDRIEntPriv
->drmFD
== pDRIPriv
->drmFD
) {
750 DRIDrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Closed DRM master.\n");
751 pDRIEntPriv
->drmFD
= -1;
756 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, NULL
);
760 #define DRM_MSG_VERBOSITY 3
763 dri_drm_debug_print(const char *format
, va_list ap
)
765 xf86VDrvMsgVerb(-1, X_NONE
, DRM_MSG_VERBOSITY
, format
, ap
);
770 dri_drm_get_perms(gid_t
* group
, mode_t
* mode
)
772 *group
= xf86ConfigDRI
.group
;
773 *mode
= xf86ConfigDRI
.mode
;
776 drmServerInfo DRIDRMServerInfo
= {
778 xf86LoadKernelModule
,
783 DRIExtensionInit(void)
785 if (DRIGeneration
!= serverGeneration
) {
789 DRIDrawablePrivResType
= CreateNewResourceType(DRIDrawablePrivDelete
,
791 DRIContextPrivResType
= CreateNewResourceType(DRIContextPrivDelete
,
794 if (!DRIDrawablePrivResType
|| !DRIContextPrivResType
)
797 RegisterBlockAndWakeupHandlers(DRIBlockHandler
, DRIWakeupHandler
, NULL
);
806 * This stub routine is called when the X Server recycles, resources
807 * allocated by DRIExtensionInit need to be managed here.
809 * Currently this routine is a stub because all the interesting resources
810 * are managed via the screen init process.
815 DRIQueryDirectRenderingCapable(ScreenPtr pScreen
, Bool
*isCapable
)
817 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
820 *isCapable
= pDRIPriv
->directRenderingSupport
;
828 DRIOpenConnection(ScreenPtr pScreen
, drm_handle_t
* hSAREA
, char **busIdString
)
830 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
832 *hSAREA
= pDRIPriv
->hSAREA
;
833 *busIdString
= pDRIPriv
->pDriverInfo
->busIdString
;
839 DRIAuthConnection(ScreenPtr pScreen
, drm_magic_t magic
)
841 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
843 if (drmAuthMagic(pDRIPriv
->drmFD
, magic
))
849 DRICloseConnection(ScreenPtr pScreen
)
855 DRIGetClientDriverName(ScreenPtr pScreen
,
856 int *ddxDriverMajorVersion
,
857 int *ddxDriverMinorVersion
,
858 int *ddxDriverPatchVersion
, char **clientDriverName
)
860 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
862 *ddxDriverMajorVersion
= pDRIPriv
->pDriverInfo
->ddxDriverMajorVersion
;
863 *ddxDriverMinorVersion
= pDRIPriv
->pDriverInfo
->ddxDriverMinorVersion
;
864 *ddxDriverPatchVersion
= pDRIPriv
->pDriverInfo
->ddxDriverPatchVersion
;
865 *clientDriverName
= pDRIPriv
->pDriverInfo
->clientDriverName
;
870 /* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper
871 functions that layer on drmCreateContext and drmAddContextTag.
873 DRICreateContextPriv always creates a kernel drm_context_t and then calls
874 DRICreateContextPrivFromHandle to create a DRIContextPriv structure for
875 DRI tracking. For the SIGIO handler, the drm_context_t is associated with
876 DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv
877 area and are passed to the kernel (if necessary).
879 DRICreateContextPriv returns a pointer to newly allocated
880 DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */
883 DRICreateContextPriv(ScreenPtr pScreen
,
884 drm_context_t
* pHWContext
, DRIContextFlags flags
)
886 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
888 if (drmCreateContext(pDRIPriv
->drmFD
, pHWContext
)) {
892 return DRICreateContextPrivFromHandle(pScreen
, *pHWContext
, flags
);
896 DRICreateContextPrivFromHandle(ScreenPtr pScreen
,
897 drm_context_t hHWContext
, DRIContextFlags flags
)
899 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
900 DRIContextPrivPtr pDRIContextPriv
;
903 contextPrivSize
= sizeof(DRIContextPrivRec
) +
904 pDRIPriv
->pDriverInfo
->contextSize
;
905 if (!(pDRIContextPriv
= calloc(1, contextPrivSize
))) {
908 pDRIContextPriv
->pContextStore
= (void *) (pDRIContextPriv
+ 1);
910 drmAddContextTag(pDRIPriv
->drmFD
, hHWContext
, pDRIContextPriv
);
912 pDRIContextPriv
->hwContext
= hHWContext
;
913 pDRIContextPriv
->pScreen
= pScreen
;
914 pDRIContextPriv
->flags
= flags
;
915 pDRIContextPriv
->valid3D
= FALSE
;
917 if (flags
& DRI_CONTEXT_2DONLY
) {
918 if (drmSetContextFlags(pDRIPriv
->drmFD
, hHWContext
, DRM_CONTEXT_2DONLY
)) {
919 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
920 "[drm] failed to set 2D context flag\n");
921 DRIDestroyContextPriv(pDRIContextPriv
);
925 if (flags
& DRI_CONTEXT_PRESERVED
) {
926 if (drmSetContextFlags(pDRIPriv
->drmFD
,
927 hHWContext
, DRM_CONTEXT_PRESERVED
)) {
928 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
929 "[drm] failed to set preserved flag\n");
930 DRIDestroyContextPriv(pDRIContextPriv
);
934 return pDRIContextPriv
;
938 DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv
)
940 DRIScreenPrivPtr pDRIPriv
;
942 if (!pDRIContextPriv
)
945 pDRIPriv
= DRI_SCREEN_PRIV(pDRIContextPriv
->pScreen
);
947 if (!(pDRIContextPriv
->flags
& DRI_CONTEXT_RESERVED
)) {
948 /* Don't delete reserved contexts from
949 kernel area -- the kernel manages its
950 reserved contexts itself. */
951 if (drmDestroyContext(pDRIPriv
->drmFD
, pDRIContextPriv
->hwContext
))
955 /* Remove the tag last to prevent a race
956 condition where the context has pending
957 buffers. The context can't be re-used
958 while in this thread, but buffers can be
959 dispatched asynchronously. */
960 drmDelContextTag(pDRIPriv
->drmFD
, pDRIContextPriv
->hwContext
);
961 free(pDRIContextPriv
);
966 DRICreateDummyContext(ScreenPtr pScreen
, Bool needCtxPriv
)
968 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
969 DRIContextPrivPtr pDRIContextPriv
;
972 if (!(pDRIContextPriv
=
973 DRICreateContextPriv(pScreen
, &pDRIPriv
->pSAREA
->dummy_context
, 0))) {
977 contextStore
= DRIGetContextStore(pDRIContextPriv
);
978 if (pDRIPriv
->pDriverInfo
->CreateContext
&& needCtxPriv
) {
979 if (!pDRIPriv
->pDriverInfo
->CreateContext(pScreen
, NULL
,
982 (DRIContextType
) (long)
984 DRIDestroyContextPriv(pDRIContextPriv
);
989 pDRIPriv
->dummyCtxPriv
= pDRIContextPriv
;
994 DRIDestroyDummyContext(ScreenPtr pScreen
, Bool hasCtxPriv
)
996 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
997 DRIContextPrivPtr pDRIContextPriv
= pDRIPriv
->dummyCtxPriv
;
1000 if (!pDRIContextPriv
)
1002 if (pDRIPriv
->pDriverInfo
->DestroyContext
&& hasCtxPriv
) {
1003 contextStore
= DRIGetContextStore(pDRIContextPriv
);
1004 pDRIPriv
->pDriverInfo
->DestroyContext(pDRIContextPriv
->pScreen
,
1005 pDRIContextPriv
->hwContext
,
1006 (DRIContextType
) (long)
1010 DRIDestroyContextPriv(pDRIPriv
->dummyCtxPriv
);
1011 pDRIPriv
->dummyCtxPriv
= NULL
;
1015 DRICreateContext(ScreenPtr pScreen
, VisualPtr visual
,
1016 XID context
, drm_context_t
* pHWContext
)
1018 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1019 DRIContextPrivPtr pDRIContextPriv
;
1022 if (pDRIPriv
->createDummyCtx
&& !pDRIPriv
->dummyCtxPriv
) {
1023 if (!DRICreateDummyContext(pScreen
, pDRIPriv
->createDummyCtxPriv
)) {
1024 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
1025 "[drm] Could not create dummy context\n");
1030 if (!(pDRIContextPriv
= DRICreateContextPriv(pScreen
, pHWContext
, 0))) {
1034 contextStore
= DRIGetContextStore(pDRIContextPriv
);
1035 if (pDRIPriv
->pDriverInfo
->CreateContext
) {
1036 if (!((*pDRIPriv
->pDriverInfo
->CreateContext
) (pScreen
, NULL
,
1038 (DRIContextType
) (long)
1040 DRIDestroyContextPriv(pDRIContextPriv
);
1045 /* track this in case the client dies before cleanup */
1046 AddResource(context
, DRIContextPrivResType
, (pointer
) pDRIContextPriv
);
1052 DRIDestroyContext(ScreenPtr pScreen
, XID context
)
1054 FreeResourceByType(context
, DRIContextPrivResType
, FALSE
);
1059 /* DRIContextPrivDelete is called by the resource manager. */
1061 DRIContextPrivDelete(pointer pResource
, XID id
)
1063 DRIContextPrivPtr pDRIContextPriv
= (DRIContextPrivPtr
) pResource
;
1064 DRIScreenPrivPtr pDRIPriv
;
1067 pDRIPriv
= DRI_SCREEN_PRIV(pDRIContextPriv
->pScreen
);
1068 if (pDRIPriv
->pDriverInfo
->DestroyContext
) {
1069 contextStore
= DRIGetContextStore(pDRIContextPriv
);
1070 pDRIPriv
->pDriverInfo
->DestroyContext(pDRIContextPriv
->pScreen
,
1071 pDRIContextPriv
->hwContext
,
1072 (DRIContextType
) (long)
1075 return DRIDestroyContextPriv(pDRIContextPriv
);
1078 /* This walks the drawable timestamp array and invalidates all of them
1079 * in the case of transition from private to shared backbuffers. It's
1080 * not necessary for correctness, because DRIClipNotify gets called in
1081 * time to prevent any conflict, but the transition from
1082 * shared->private is sometimes missed if we don't do this.
1085 DRIClipNotifyAllDrawables(ScreenPtr pScreen
)
1088 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1090 for (i
= 0; i
< pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
; i
++) {
1091 pDRIPriv
->pSAREA
->drawableTable
[i
].stamp
= DRIDrawableValidationStamp
++;
1096 DRITransitionToSharedBuffers(ScreenPtr pScreen
)
1098 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1099 DRIInfoPtr pDRIInfo
= pDRIPriv
->pDriverInfo
;
1101 DRIClipNotifyAllDrawables(pScreen
);
1103 if (pDRIInfo
->TransitionSingleToMulti3D
)
1104 pDRIInfo
->TransitionSingleToMulti3D(pScreen
);
1108 DRITransitionToPrivateBuffers(ScreenPtr pScreen
)
1110 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1111 DRIInfoPtr pDRIInfo
= pDRIPriv
->pDriverInfo
;
1113 DRIClipNotifyAllDrawables(pScreen
);
1115 if (pDRIInfo
->TransitionMultiToSingle3D
)
1116 pDRIInfo
->TransitionMultiToSingle3D(pScreen
);
1120 DRITransitionTo3d(ScreenPtr pScreen
)
1122 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1123 DRIInfoPtr pDRIInfo
= pDRIPriv
->pDriverInfo
;
1125 DRIClipNotifyAllDrawables(pScreen
);
1127 if (pDRIInfo
->TransitionTo3d
)
1128 pDRIInfo
->TransitionTo3d(pScreen
);
1132 DRITransitionTo2d(ScreenPtr pScreen
)
1134 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1135 DRIInfoPtr pDRIInfo
= pDRIPriv
->pDriverInfo
;
1137 DRIClipNotifyAllDrawables(pScreen
);
1139 if (pDRIInfo
->TransitionTo2d
)
1140 pDRIInfo
->TransitionTo2d(pScreen
);
1144 DRIDCNTreeTraversal(WindowPtr pWin
, pointer data
)
1146 DRIDrawablePrivPtr pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
1148 if (pDRIDrawablePriv
) {
1149 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
1150 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1152 if (RegionNumRects(&pWin
->clipList
) > 0) {
1153 WindowPtr
*pDRIWindows
= (WindowPtr
*) data
;
1156 while (pDRIWindows
[i
])
1159 pDRIWindows
[i
] = pWin
;
1161 pDRIPriv
->nrWalked
++;
1164 if (pDRIPriv
->nrWindows
== pDRIPriv
->nrWalked
)
1165 return WT_STOPWALKING
;
1168 return WT_WALKCHILDREN
;
1172 DRIDriverClipNotify(ScreenPtr pScreen
)
1174 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1176 if (pDRIPriv
->pDriverInfo
->ClipNotify
) {
1177 WindowPtr
*pDRIWindows
= calloc(sizeof(WindowPtr
), pDRIPriv
->nrWindows
);
1178 DRIInfoPtr pDRIInfo
= pDRIPriv
->pDriverInfo
;
1180 if (pDRIPriv
->nrWindows
> 0) {
1181 pDRIPriv
->nrWalked
= 0;
1182 TraverseTree(pScreen
->root
, DRIDCNTreeTraversal
,
1183 (pointer
) pDRIWindows
);
1186 pDRIInfo
->ClipNotify(pScreen
, pDRIWindows
, pDRIPriv
->nrWindows
);
1193 DRIIncreaseNumberVisible(ScreenPtr pScreen
)
1195 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1197 switch (++pDRIPriv
->nrWindowsVisible
) {
1199 DRITransitionTo3d(pScreen
);
1202 DRITransitionToSharedBuffers(pScreen
);
1208 DRIDriverClipNotify(pScreen
);
1212 DRIDecreaseNumberVisible(ScreenPtr pScreen
)
1214 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1216 switch (--pDRIPriv
->nrWindowsVisible
) {
1218 DRITransitionTo2d(pScreen
);
1221 DRITransitionToPrivateBuffers(pScreen
);
1227 DRIDriverClipNotify(pScreen
);
1231 DRICreateDrawable(ScreenPtr pScreen
, ClientPtr client
, DrawablePtr pDrawable
,
1232 drm_drawable_t
* hHWDrawable
)
1234 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1235 DRIDrawablePrivPtr pDRIDrawablePriv
;
1238 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
1239 pWin
= (WindowPtr
) pDrawable
;
1240 if ((pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
))) {
1241 pDRIDrawablePriv
->refCount
++;
1243 if (!pDRIDrawablePriv
->hwDrawable
) {
1244 drmCreateDrawable(pDRIPriv
->drmFD
,
1245 &pDRIDrawablePriv
->hwDrawable
);
1249 /* allocate a DRI Window Private record */
1250 if (!(pDRIDrawablePriv
= malloc(sizeof(DRIDrawablePrivRec
)))) {
1254 /* Only create a drm_drawable_t once */
1255 if (drmCreateDrawable(pDRIPriv
->drmFD
,
1256 &pDRIDrawablePriv
->hwDrawable
)) {
1257 free(pDRIDrawablePriv
);
1261 /* add it to the list of DRI drawables for this screen */
1262 pDRIDrawablePriv
->pScreen
= pScreen
;
1263 pDRIDrawablePriv
->refCount
= 1;
1264 pDRIDrawablePriv
->drawableIndex
= -1;
1265 pDRIDrawablePriv
->nrects
= RegionNumRects(&pWin
->clipList
);
1267 /* save private off of preallocated index */
1268 dixSetPrivate(&pWin
->devPrivates
, DRIWindowPrivKey
,
1270 pDRIPriv
->nrWindows
++;
1272 if (pDRIDrawablePriv
->nrects
)
1273 DRIIncreaseNumberVisible(pScreen
);
1276 /* track this in case the client dies */
1277 AddResource(FakeClientID(client
->index
), DRIDrawablePrivResType
,
1278 (pointer
) (intptr_t) pDrawable
->id
);
1280 if (pDRIDrawablePriv
->hwDrawable
) {
1281 drmUpdateDrawableInfo(pDRIPriv
->drmFD
,
1282 pDRIDrawablePriv
->hwDrawable
,
1283 DRM_DRAWABLE_CLIPRECTS
,
1284 RegionNumRects(&pWin
->clipList
),
1285 RegionRects(&pWin
->clipList
));
1286 *hHWDrawable
= pDRIDrawablePriv
->hwDrawable
;
1289 else if (pDrawable
->type
!= DRAWABLE_PIXMAP
) { /* PBuffer */
1298 DRIDrawablePrivDestroy(WindowPtr pWin
)
1300 DRIDrawablePrivPtr pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
1302 DRIScreenPrivPtr pDRIPriv
;
1304 if (!pDRIDrawablePriv
)
1307 pScreen
= pWin
->drawable
.pScreen
;
1308 pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1310 if (pDRIDrawablePriv
->drawableIndex
!= -1) {
1311 /* bump stamp to force outstanding 3D requests to resync */
1312 pDRIPriv
->pSAREA
->drawableTable
[pDRIDrawablePriv
->drawableIndex
].stamp
1313 = DRIDrawableValidationStamp
++;
1315 /* release drawable table entry */
1316 pDRIPriv
->DRIDrawables
[pDRIDrawablePriv
->drawableIndex
] = NULL
;
1319 pDRIPriv
->nrWindows
--;
1321 if (pDRIDrawablePriv
->nrects
)
1322 DRIDecreaseNumberVisible(pScreen
);
1324 drmDestroyDrawable(pDRIPriv
->drmFD
, pDRIDrawablePriv
->hwDrawable
);
1326 free(pDRIDrawablePriv
);
1327 dixSetPrivate(&pWin
->devPrivates
, DRIWindowPrivKey
, NULL
);
1331 DRIDestroyDrawableCB(pointer value
, XID id
, pointer data
)
1333 if (value
== data
) {
1334 /* This calls back DRIDrawablePrivDelete which frees private area */
1335 FreeResourceByType(id
, DRIDrawablePrivResType
, FALSE
);
1344 DRIDestroyDrawable(ScreenPtr pScreen
, ClientPtr client
, DrawablePtr pDrawable
)
1346 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
1347 LookupClientResourceComplex(client
, DRIDrawablePrivResType
,
1348 DRIDestroyDrawableCB
,
1349 (pointer
) (intptr_t) pDrawable
->id
);
1351 else { /* pixmap (or for GLX 1.3, a PBuffer) */
1360 DRIDrawablePrivDelete(pointer pResource
, XID id
)
1365 /* For DRIDrawablePrivResType, the XID is the client's fake ID. The
1366 * important XID is the value in pResource. */
1367 id
= (XID
) (intptr_t) pResource
;
1368 rc
= dixLookupWindow(&pWin
, id
, serverClient
, DixGetAttrAccess
);
1370 if (rc
== Success
) {
1371 DRIDrawablePrivPtr pDRIDrwPriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
1376 if (--pDRIDrwPriv
->refCount
== 0)
1377 DRIDrawablePrivDestroy(pWin
);
1381 else { /* pixmap (or for GLX 1.3, a PBuffer) */
1388 DRIGetDrawableInfo(ScreenPtr pScreen
,
1389 DrawablePtr pDrawable
,
1390 unsigned int *index
,
1391 unsigned int *stamp
,
1397 drm_clip_rect_t
** pClipRects
,
1400 int *numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
1402 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1403 DRIDrawablePrivPtr pDRIDrawablePriv
, pOldDrawPriv
;
1404 WindowPtr pWin
, pOldWin
;
1408 printf("maxDrawableTableEntry = %d\n",
1409 pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
);
1412 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
1413 pWin
= (WindowPtr
) pDrawable
;
1414 if ((pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
))) {
1416 /* Manage drawable table */
1417 if (pDRIDrawablePriv
->drawableIndex
== -1) { /* load SAREA table */
1419 /* Search table for empty entry */
1421 while (i
< pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
) {
1422 if (!(pDRIPriv
->DRIDrawables
[i
])) {
1423 pDRIPriv
->DRIDrawables
[i
] = pDrawable
;
1424 pDRIDrawablePriv
->drawableIndex
= i
;
1425 pDRIPriv
->pSAREA
->drawableTable
[i
].stamp
=
1426 DRIDrawableValidationStamp
++;
1432 /* Search table for oldest entry */
1433 if (i
== pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
) {
1434 unsigned int oldestStamp
= ~0;
1435 int oldestIndex
= 0;
1437 i
= pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
;
1439 if (pDRIPriv
->pSAREA
->drawableTable
[i
].stamp
<
1443 pDRIPriv
->pSAREA
->drawableTable
[i
].stamp
;
1446 pDRIDrawablePriv
->drawableIndex
= oldestIndex
;
1448 /* release oldest drawable table entry */
1449 pOldWin
= (WindowPtr
) pDRIPriv
->DRIDrawables
[oldestIndex
];
1450 pOldDrawPriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin
);
1451 pOldDrawPriv
->drawableIndex
= -1;
1453 /* claim drawable table entry */
1454 pDRIPriv
->DRIDrawables
[oldestIndex
] = pDrawable
;
1456 /* validate SAREA entry */
1457 pDRIPriv
->pSAREA
->drawableTable
[oldestIndex
].stamp
=
1458 DRIDrawableValidationStamp
++;
1460 /* check for stamp wrap around */
1461 if (oldestStamp
> DRIDrawableValidationStamp
) {
1463 /* walk SAREA table and invalidate all drawables */
1465 i
< pDRIPriv
->pDriverInfo
->maxDrawableTableEntry
;
1467 pDRIPriv
->pSAREA
->drawableTable
[i
].stamp
=
1468 DRIDrawableValidationStamp
++;
1473 /* If the driver wants to be notified when the index is
1474 * set for a drawable, let it know now.
1476 if (pDRIPriv
->pDriverInfo
->SetDrawableIndex
)
1477 pDRIPriv
->pDriverInfo
->SetDrawableIndex(pWin
,
1481 /* reinit drawable ID if window is visible */
1482 if ((pWin
->viewable
) &&
1483 (pDRIPriv
->pDriverInfo
->bufferRequests
!= DRI_NO_WINDOWS
)) {
1484 (*pDRIPriv
->pDriverInfo
->InitBuffers
) (pWin
,
1491 *index
= pDRIDrawablePriv
->drawableIndex
;
1492 *stamp
= pDRIPriv
->pSAREA
->drawableTable
[*index
].stamp
;
1493 *X
= (int) (pWin
->drawable
.x
);
1494 *Y
= (int) (pWin
->drawable
.y
);
1495 *W
= (int) (pWin
->drawable
.width
);
1496 *H
= (int) (pWin
->drawable
.height
);
1497 *numClipRects
= RegionNumRects(&pWin
->clipList
);
1498 *pClipRects
= (drm_clip_rect_t
*) RegionRects(&pWin
->clipList
);
1500 if (!*numClipRects
&& pDRIPriv
->fullscreen
) {
1501 /* use fake full-screen clip rect */
1502 pDRIPriv
->fullscreen_rect
.x1
= *X
;
1503 pDRIPriv
->fullscreen_rect
.y1
= *Y
;
1504 pDRIPriv
->fullscreen_rect
.x2
= *X
+ *W
;
1505 pDRIPriv
->fullscreen_rect
.y2
= *Y
+ *H
;
1508 *pClipRects
= &pDRIPriv
->fullscreen_rect
;
1514 if (pDRIPriv
->nrWindowsVisible
== 1 && *numClipRects
) {
1515 /* Use a single cliprect. */
1526 if (x1
> pScreen
->width
)
1527 x1
= pScreen
->width
;
1528 if (y1
> pScreen
->height
)
1529 y1
= pScreen
->height
;
1531 if (y0
>= y1
|| x0
>= x1
) {
1532 *numBackClipRects
= 0;
1533 *pBackClipRects
= NULL
;
1536 pDRIPriv
->private_buffer_rect
.x1
= x0
;
1537 pDRIPriv
->private_buffer_rect
.y1
= y0
;
1538 pDRIPriv
->private_buffer_rect
.x2
= x1
;
1539 pDRIPriv
->private_buffer_rect
.y2
= y1
;
1541 *numBackClipRects
= 1;
1542 *pBackClipRects
= &(pDRIPriv
->private_buffer_rect
);
1546 /* Use the frontbuffer cliprects for back buffers. */
1547 *numBackClipRects
= 0;
1548 *pBackClipRects
= 0;
1552 /* Not a DRIDrawable */
1556 else { /* pixmap (or for GLX 1.3, a PBuffer) */
1565 DRIGetDeviceInfo(ScreenPtr pScreen
,
1566 drm_handle_t
* hFrameBuffer
,
1569 int *fbStride
, int *devPrivateSize
, void **pDevPrivate
)
1571 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1573 *hFrameBuffer
= pDRIPriv
->pDriverInfo
->hFrameBuffer
;
1575 *fbSize
= pDRIPriv
->pDriverInfo
->frameBufferSize
;
1576 *fbStride
= pDRIPriv
->pDriverInfo
->frameBufferStride
;
1577 *devPrivateSize
= pDRIPriv
->pDriverInfo
->devPrivateSize
;
1578 *pDevPrivate
= pDRIPriv
->pDriverInfo
->devPrivate
;
1584 DRICreateInfoRec(void)
1586 DRIInfoPtr inforec
= (DRIInfoPtr
) calloc(1, sizeof(DRIInfoRec
));
1591 /* Initialize defaults */
1592 inforec
->busIdString
= NULL
;
1594 /* Wrapped function defaults */
1595 inforec
->wrap
.WakeupHandler
= DRIDoWakeupHandler
;
1596 inforec
->wrap
.BlockHandler
= DRIDoBlockHandler
;
1597 inforec
->wrap
.WindowExposures
= DRIWindowExposures
;
1598 inforec
->wrap
.CopyWindow
= DRICopyWindow
;
1599 inforec
->wrap
.ValidateTree
= DRIValidateTree
;
1600 inforec
->wrap
.PostValidateTree
= DRIPostValidateTree
;
1601 inforec
->wrap
.ClipNotify
= DRIClipNotify
;
1602 inforec
->wrap
.AdjustFrame
= DRIAdjustFrame
;
1604 inforec
->TransitionTo2d
= 0;
1605 inforec
->TransitionTo3d
= 0;
1606 inforec
->SetDrawableIndex
= 0;
1612 DRIDestroyInfoRec(DRIInfoPtr DRIInfo
)
1614 free(DRIInfo
->busIdString
);
1615 free((char *) DRIInfo
);
1619 DRIWakeupHandler(pointer wakeupData
, int result
, pointer pReadmask
)
1623 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1624 ScreenPtr pScreen
= screenInfo
.screens
[i
];
1625 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1627 if (pDRIPriv
&& pDRIPriv
->pDriverInfo
->wrap
.WakeupHandler
)
1628 (*pDRIPriv
->pDriverInfo
->wrap
.WakeupHandler
) (pScreen
,
1634 DRIBlockHandler(pointer blockData
, OSTimePtr pTimeout
, pointer pReadmask
)
1638 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1639 ScreenPtr pScreen
= screenInfo
.screens
[i
];
1640 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1642 if (pDRIPriv
&& pDRIPriv
->pDriverInfo
->wrap
.BlockHandler
)
1643 (*pDRIPriv
->pDriverInfo
->wrap
.BlockHandler
) (pScreen
,
1644 pTimeout
, pReadmask
);
1649 DRIDoWakeupHandler(ScreenPtr pScreen
,
1650 unsigned long result
, pointer pReadmask
)
1652 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1654 DRILock(pScreen
, 0);
1655 if (pDRIPriv
->pDriverInfo
->driverSwapMethod
== DRI_HIDE_X_CONTEXT
) {
1656 /* hide X context by swapping 2D component here */
1657 (*pDRIPriv
->pDriverInfo
->SwapContext
) (pScreen
,
1660 pDRIPriv
->partial3DContextStore
,
1662 pDRIPriv
->hiddenContextStore
);
1667 DRIDoBlockHandler(ScreenPtr pScreen
,
1668 pointer pTimeout
, pointer pReadmask
)
1670 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1672 if (pDRIPriv
->pDriverInfo
->driverSwapMethod
== DRI_HIDE_X_CONTEXT
) {
1673 /* hide X context by swapping 2D component here */
1674 (*pDRIPriv
->pDriverInfo
->SwapContext
) (pScreen
,
1679 pDRIPriv
->partial3DContextStore
);
1682 if (pDRIPriv
->windowsTouched
)
1683 DRM_SPINUNLOCK(&pDRIPriv
->pSAREA
->drawable_lock
, 1);
1684 pDRIPriv
->windowsTouched
= FALSE
;
1690 DRISwapContext(int drmFD
, void *oldctx
, void *newctx
)
1692 DRIContextPrivPtr oldContext
= (DRIContextPrivPtr
) oldctx
;
1693 DRIContextPrivPtr newContext
= (DRIContextPrivPtr
) newctx
;
1694 ScreenPtr pScreen
= newContext
->pScreen
;
1695 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1696 void *oldContextStore
= NULL
;
1697 DRIContextType oldContextType
;
1698 void *newContextStore
= NULL
;
1699 DRIContextType newContextType
;
1700 DRISyncType syncType
;
1703 static int count
= 0;
1706 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
1707 "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n",
1708 oldContext
, newContext
);
1712 /* usefull for debugging, just print out after n context switches */
1713 if (!count
|| !(count
% 1)) {
1714 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
1715 "[DRI] Context switch %5d from %p/0x%08x (%d)\n",
1718 oldContext
? oldContext
->flags
: 0,
1719 oldContext
? oldContext
->hwContext
: -1);
1720 DRIDrvMsg(pScreen
->myNum
, X_INFO
,
1721 "[DRI] Context switch %5d to %p/0x%08x (%d)\n",
1724 newContext
? newContext
->flags
: 0,
1725 newContext
? newContext
->hwContext
: -1);
1730 if (!pDRIPriv
->pDriverInfo
->SwapContext
) {
1731 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
1732 "[DRI] DDX driver missing context swap call back\n");
1736 if (pDRIPriv
->pDriverInfo
->driverSwapMethod
== DRI_HIDE_X_CONTEXT
) {
1738 /* only 3D contexts are swapped in this case */
1740 oldContextStore
= DRIGetContextStore(oldContext
);
1741 oldContext
->valid3D
= TRUE
;
1742 oldContextType
= DRI_3D_CONTEXT
;
1745 oldContextType
= DRI_NO_CONTEXT
;
1747 newContextStore
= DRIGetContextStore(newContext
);
1748 if ((newContext
->valid3D
) &&
1749 (newContext
->hwContext
!= pDRIPriv
->myContext
)) {
1750 newContextType
= DRI_3D_CONTEXT
;
1753 newContextType
= DRI_2D_CONTEXT
;
1755 syncType
= DRI_3D_SYNC
;
1757 else { /* default: driverSwapMethod == DRI_SERVER_SWAP */
1759 /* optimize 2D context swaps */
1761 if (newContext
->flags
& DRI_CONTEXT_2DONLY
) {
1762 /* go from 3D context to 2D context and only save 2D
1763 * subset of 3D state
1765 oldContextStore
= DRIGetContextStore(oldContext
);
1766 oldContextType
= DRI_2D_CONTEXT
;
1767 newContextStore
= DRIGetContextStore(newContext
);
1768 newContextType
= DRI_2D_CONTEXT
;
1769 syncType
= DRI_3D_SYNC
;
1770 pDRIPriv
->lastPartial3DContext
= oldContext
;
1772 else if (oldContext
->flags
& DRI_CONTEXT_2DONLY
) {
1773 if (pDRIPriv
->lastPartial3DContext
== newContext
) {
1774 /* go from 2D context back to previous 3D context and
1775 * only restore 2D subset of previous 3D state
1777 oldContextStore
= DRIGetContextStore(oldContext
);
1778 oldContextType
= DRI_2D_CONTEXT
;
1779 newContextStore
= DRIGetContextStore(newContext
);
1780 newContextType
= DRI_2D_CONTEXT
;
1781 syncType
= DRI_2D_SYNC
;
1784 /* go from 2D context to a different 3D context */
1786 /* call DDX driver to do partial restore */
1787 oldContextStore
= DRIGetContextStore(oldContext
);
1789 DRIGetContextStore(pDRIPriv
->lastPartial3DContext
);
1790 (*pDRIPriv
->pDriverInfo
->SwapContext
) (pScreen
,
1797 /* now setup for a complete 3D swap */
1798 oldContextStore
= newContextStore
;
1799 oldContext
->valid3D
= TRUE
;
1800 oldContextType
= DRI_3D_CONTEXT
;
1801 newContextStore
= DRIGetContextStore(newContext
);
1802 if ((newContext
->valid3D
) &&
1803 (newContext
->hwContext
!= pDRIPriv
->myContext
)) {
1804 newContextType
= DRI_3D_CONTEXT
;
1807 newContextType
= DRI_2D_CONTEXT
;
1809 syncType
= DRI_NO_SYNC
;
1813 /* now setup for a complete 3D swap */
1814 oldContextStore
= newContextStore
;
1815 oldContext
->valid3D
= TRUE
;
1816 oldContextType
= DRI_3D_CONTEXT
;
1817 newContextStore
= DRIGetContextStore(newContext
);
1818 if ((newContext
->valid3D
) &&
1819 (newContext
->hwContext
!= pDRIPriv
->myContext
)) {
1820 newContextType
= DRI_3D_CONTEXT
;
1823 newContextType
= DRI_2D_CONTEXT
;
1825 syncType
= DRI_3D_SYNC
;
1829 /* call DDX driver to perform the swap */
1830 (*pDRIPriv
->pDriverInfo
->SwapContext
) (pScreen
,
1834 newContextType
, newContextStore
);
1838 DRIGetContextStore(DRIContextPrivPtr context
)
1840 return ((void *) context
->pContextStore
);
1844 DRIWindowExposures(WindowPtr pWin
, RegionPtr prgn
, RegionPtr bsreg
)
1846 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
1847 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1848 DRIDrawablePrivPtr pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
1850 if (pDRIDrawablePriv
) {
1851 (*pDRIPriv
->pDriverInfo
->InitBuffers
) (pWin
, prgn
,
1852 pDRIDrawablePriv
->drawableIndex
);
1855 /* call lower wrapped functions */
1856 if (pDRIPriv
&& pDRIPriv
->wrap
.WindowExposures
) {
1859 pScreen
->WindowExposures
= pDRIPriv
->wrap
.WindowExposures
;
1861 /* call lower layers */
1862 (*pScreen
->WindowExposures
) (pWin
, prgn
, bsreg
);
1865 pDRIPriv
->wrap
.WindowExposures
= pScreen
->WindowExposures
;
1866 pScreen
->WindowExposures
= DRIWindowExposures
;
1871 DRITreeTraversal(WindowPtr pWin
, pointer data
)
1873 DRIDrawablePrivPtr pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
1875 if (pDRIDrawablePriv
) {
1876 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
1877 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1879 if (RegionNumRects(&(pWin
->clipList
)) > 0) {
1880 RegionPtr reg
= (RegionPtr
) data
;
1882 RegionUnion(reg
, reg
, &(pWin
->clipList
));
1883 pDRIPriv
->nrWalked
++;
1886 if (pDRIPriv
->nrWindows
== pDRIPriv
->nrWalked
)
1887 return WT_STOPWALKING
;
1889 return WT_WALKCHILDREN
;
1893 DRIDestroyWindow(WindowPtr pWin
)
1895 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
1896 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1899 DRIDrawablePrivDestroy(pWin
);
1901 /* call lower wrapped functions */
1902 if (pDRIPriv
->DestroyWindow
) {
1904 pScreen
->DestroyWindow
= pDRIPriv
->DestroyWindow
;
1906 /* call lower layers */
1907 retval
= (*pScreen
->DestroyWindow
) (pWin
);
1910 pDRIPriv
->DestroyWindow
= pScreen
->DestroyWindow
;
1911 pScreen
->DestroyWindow
= DRIDestroyWindow
;
1918 DRICopyWindow(WindowPtr pWin
, DDXPointRec ptOldOrg
, RegionPtr prgnSrc
)
1920 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
1921 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
1926 if (pDRIPriv
->nrWindowsVisible
> 0) {
1930 pDRIPriv
->nrWalked
= 0;
1931 TraverseTree(pWin
, DRITreeTraversal
, (pointer
) (®
));
1933 if (RegionNotEmpty(®
)) {
1934 RegionTranslate(®
, ptOldOrg
.x
- pWin
->drawable
.x
,
1935 ptOldOrg
.y
- pWin
->drawable
.y
);
1936 RegionIntersect(®
, ®
, prgnSrc
);
1938 /* The MoveBuffers interface is not ideal */
1939 (*pDRIPriv
->pDriverInfo
->MoveBuffers
) (pWin
, ptOldOrg
, ®
,
1940 pDRIPriv
->pDriverInfo
->
1941 ddxDrawableTableEntry
);
1947 /* call lower wrapped functions */
1948 if (pDRIPriv
->wrap
.CopyWindow
) {
1950 pScreen
->CopyWindow
= pDRIPriv
->wrap
.CopyWindow
;
1952 /* call lower layers */
1953 (*pScreen
->CopyWindow
) (pWin
, ptOldOrg
, prgnSrc
);
1956 pDRIPriv
->wrap
.CopyWindow
= pScreen
->CopyWindow
;
1957 pScreen
->CopyWindow
= DRICopyWindow
;
1962 DRIGetSecs(long *secs
, long *usecs
)
1966 gettimeofday(&tv
, NULL
);
1969 *usecs
= tv
.tv_usec
;
1972 static unsigned long
1973 DRIComputeMilliSeconds(unsigned long s_secs
, unsigned long s_usecs
,
1974 unsigned long f_secs
, unsigned long f_usecs
)
1976 if (f_usecs
< s_usecs
) {
1980 return (f_secs
- s_secs
) * 1000 + (f_usecs
- s_usecs
) / 1000;
1984 DRISpinLockTimeout(drmLock
* lock
, int val
, unsigned long timeout
/* in mS */ )
1988 #if !defined(__alpha__) && !defined(__powerpc__)
1993 long s_secs
, s_usecs
;
1994 long f_secs
, f_usecs
;
1998 DRIGetSecs(&s_secs
, &s_usecs
);
2001 DRM_SPINLOCK_COUNT(lock
, val
, count
, ret
);
2003 return; /* Got lock */
2004 DRIGetSecs(&f_secs
, &f_usecs
);
2005 msecs
= DRIComputeMilliSeconds(s_secs
, s_usecs
, f_secs
, f_usecs
);
2006 if (msecs
- prev
< 250)
2007 count
*= 2; /* Not more than 0.5S */
2008 } while (msecs
< timeout
);
2010 /* Didn't get lock, so take it. The worst
2011 that can happen is that there is some
2012 garbage written to the wrong part of the
2013 framebuffer that a refresh will repair.
2014 That's undesirable, but better than
2015 locking the server. This should be a
2017 DRM_SPINLOCK_TAKE(lock
, val
);
2021 DRILockTree(ScreenPtr pScreen
)
2023 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2028 /* Restore the last known 3D context if the X context is hidden */
2029 if (pDRIPriv
->pDriverInfo
->driverSwapMethod
== DRI_HIDE_X_CONTEXT
) {
2030 (*pDRIPriv
->pDriverInfo
->SwapContext
) (pScreen
,
2035 pDRIPriv
->partial3DContextStore
);
2038 /* Call kernel to release lock */
2041 /* Grab drawable spin lock: a time out between 10 and 30 seconds is
2042 appropriate, since this should never time out except in the case of
2043 client death while the lock is being held. The timeout must be
2044 greater than any reasonable rendering time. */
2045 DRISpinLockTimeout(&pDRIPriv
->pSAREA
->drawable_lock
, 1, 10000); /*10 secs */
2047 /* Call kernel flush outstanding buffers and relock */
2048 DRILock(pScreen
, DRM_LOCK_QUIESCENT
| DRM_LOCK_FLUSH_ALL
);
2050 /* Switch back to our 2D context if the X context is hidden */
2051 if (pDRIPriv
->pDriverInfo
->driverSwapMethod
== DRI_HIDE_X_CONTEXT
) {
2052 /* hide X context by swapping 2D component here */
2053 (*pDRIPriv
->pDriverInfo
->SwapContext
) (pScreen
,
2056 pDRIPriv
->partial3DContextStore
,
2058 pDRIPriv
->hiddenContextStore
);
2063 DRIValidateTree(WindowPtr pParent
, WindowPtr pChild
, VTKind kind
)
2065 ScreenPtr pScreen
= pParent
->drawable
.pScreen
;
2066 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2068 int returnValue
= 1; /* always return 1, not checked by dix/window.c */
2073 /* call lower wrapped functions */
2074 if (pDRIPriv
->wrap
.ValidateTree
) {
2076 pScreen
->ValidateTree
= pDRIPriv
->wrap
.ValidateTree
;
2078 /* call lower layers */
2079 returnValue
= (*pScreen
->ValidateTree
) (pParent
, pChild
, kind
);
2082 pDRIPriv
->wrap
.ValidateTree
= pScreen
->ValidateTree
;
2083 pScreen
->ValidateTree
= DRIValidateTree
;
2090 DRIPostValidateTree(WindowPtr pParent
, WindowPtr pChild
, VTKind kind
)
2093 DRIScreenPrivPtr pDRIPriv
;
2096 pScreen
= pParent
->drawable
.pScreen
;
2099 pScreen
= pChild
->drawable
.pScreen
;
2101 if (!(pDRIPriv
= DRI_SCREEN_PRIV(pScreen
)))
2104 if (pDRIPriv
->wrap
.PostValidateTree
) {
2106 pScreen
->PostValidateTree
= pDRIPriv
->wrap
.PostValidateTree
;
2108 /* call lower layers */
2109 (*pScreen
->PostValidateTree
) (pParent
, pChild
, kind
);
2112 pDRIPriv
->wrap
.PostValidateTree
= pScreen
->PostValidateTree
;
2113 pScreen
->PostValidateTree
= DRIPostValidateTree
;
2118 DRIClipNotify(WindowPtr pWin
, int dx
, int dy
)
2120 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
2121 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2122 DRIDrawablePrivPtr pDRIDrawablePriv
;
2127 if ((pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
))) {
2128 int nrects
= RegionNumRects(&pWin
->clipList
);
2130 if (!pDRIPriv
->windowsTouched
) {
2131 DRILockTree(pScreen
);
2132 pDRIPriv
->windowsTouched
= TRUE
;
2135 if (nrects
&& !pDRIDrawablePriv
->nrects
)
2136 DRIIncreaseNumberVisible(pScreen
);
2137 else if (!nrects
&& pDRIDrawablePriv
->nrects
)
2138 DRIDecreaseNumberVisible(pScreen
);
2140 DRIDriverClipNotify(pScreen
);
2142 pDRIDrawablePriv
->nrects
= nrects
;
2144 pDRIPriv
->pSAREA
->drawableTable
[pDRIDrawablePriv
->drawableIndex
].stamp
2145 = DRIDrawableValidationStamp
++;
2147 drmUpdateDrawableInfo(pDRIPriv
->drmFD
, pDRIDrawablePriv
->hwDrawable
,
2148 DRM_DRAWABLE_CLIPRECTS
,
2149 nrects
, RegionRects(&pWin
->clipList
));
2152 /* call lower wrapped functions */
2153 if (pDRIPriv
->wrap
.ClipNotify
) {
2156 pScreen
->ClipNotify
= pDRIPriv
->wrap
.ClipNotify
;
2158 /* call lower layers */
2159 (*pScreen
->ClipNotify
) (pWin
, dx
, dy
);
2162 pDRIPriv
->wrap
.ClipNotify
= pScreen
->ClipNotify
;
2163 pScreen
->ClipNotify
= DRIClipNotify
;
2168 DRIGetDrawableIndex(WindowPtr pWin
)
2170 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
2171 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2172 DRIDrawablePrivPtr pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
2175 if (pDRIDrawablePriv
) {
2176 index
= pDRIDrawablePriv
->drawableIndex
;
2179 index
= pDRIPriv
->pDriverInfo
->ddxDrawableTableEntry
;
2186 DRIGetDrawableStamp(ScreenPtr pScreen
, CARD32 drawable_index
)
2188 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2190 return pDRIPriv
->pSAREA
->drawableTable
[drawable_index
].stamp
;
2194 DRIPrintDrawableLock(ScreenPtr pScreen
, char *msg
)
2196 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2198 ErrorF("%s: %d\n", msg
, pDRIPriv
->pSAREA
->drawable_lock
.lock
);
2202 DRILock(ScreenPtr pScreen
, int flags
)
2204 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2206 if (!pDRIPriv
|| !pDRIPriv
->pLockRefCount
)
2209 if (!*pDRIPriv
->pLockRefCount
) {
2210 DRM_LOCK(pDRIPriv
->drmFD
, pDRIPriv
->pLSAREA
, pDRIPriv
->myContext
,
2212 *pDRIPriv
->pLockingContext
= pDRIPriv
->myContext
;
2214 else if (*pDRIPriv
->pLockingContext
!= pDRIPriv
->myContext
) {
2215 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
2216 "[DRI] Locking deadlock.\n"
2217 "\tAlready locked with context %d,\n"
2218 "\ttrying to lock with context %d.\n",
2219 pDRIPriv
->pLockingContext
, pDRIPriv
->myContext
);
2221 (*pDRIPriv
->pLockRefCount
)++;
2225 DRIUnlock(ScreenPtr pScreen
)
2227 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2229 if (!pDRIPriv
|| !pDRIPriv
->pLockRefCount
)
2232 if (*pDRIPriv
->pLockRefCount
> 0) {
2233 if (pDRIPriv
->myContext
!= *pDRIPriv
->pLockingContext
) {
2234 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
2235 "[DRI] Unlocking inconsistency:\n"
2236 "\tContext %d trying to unlock lock held by context %d\n",
2237 pDRIPriv
->pLockingContext
, pDRIPriv
->myContext
);
2239 (*pDRIPriv
->pLockRefCount
)--;
2242 DRIDrvMsg(pScreen
->myNum
, X_ERROR
,
2243 "DRIUnlock called when not locked.\n");
2246 if (!*pDRIPriv
->pLockRefCount
)
2247 DRM_UNLOCK(pDRIPriv
->drmFD
, pDRIPriv
->pLSAREA
, pDRIPriv
->myContext
);
2251 DRIGetSAREAPrivate(ScreenPtr pScreen
)
2253 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2258 return (void *) (((char *) pDRIPriv
->pSAREA
) + sizeof(XF86DRISAREARec
));
2262 DRIGetContext(ScreenPtr pScreen
)
2264 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2269 return pDRIPriv
->myContext
;
2273 DRIGetTexOffsetFuncs(ScreenPtr pScreen
,
2274 DRITexOffsetStartProcPtr
* texOffsetStartFunc
,
2275 DRITexOffsetFinishProcPtr
* texOffsetFinishFunc
)
2277 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2282 *texOffsetStartFunc
= pDRIPriv
->pDriverInfo
->texOffsetStart
;
2283 *texOffsetFinishFunc
= pDRIPriv
->pDriverInfo
->texOffsetFinish
;
2286 /* This lets get at the unwrapped functions so that they can correctly
2287 * call the lowerlevel functions, and choose whether they will be
2288 * called at every level of recursion (eg in validatetree).
2290 DRIWrappedFuncsRec
*
2291 DRIGetWrappedFuncs(ScreenPtr pScreen
)
2293 return &(DRI_SCREEN_PRIV(pScreen
)->wrap
);
2296 /* note that this returns the library version, not the protocol version */
2298 DRIQueryVersion(int *majorVersion
, int *minorVersion
, int *patchVersion
)
2300 *majorVersion
= DRIINFO_MAJOR_VERSION
;
2301 *minorVersion
= DRIINFO_MINOR_VERSION
;
2302 *patchVersion
= DRIINFO_PATCH_VERSION
;
2306 _DRIAdjustFrame(ScrnInfoPtr pScrn
, DRIScreenPrivPtr pDRIPriv
, int x
, int y
)
2308 pDRIPriv
->pSAREA
->frame
.x
= x
;
2309 pDRIPriv
->pSAREA
->frame
.y
= y
;
2310 pDRIPriv
->pSAREA
->frame
.width
= pScrn
->frameX1
- x
+ 1;
2311 pDRIPriv
->pSAREA
->frame
.height
= pScrn
->frameY1
- y
+ 1;
2315 DRIAdjustFrame(ScrnInfoPtr pScrn
, int x
, int y
)
2317 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
2318 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
2321 if (!pDRIPriv
|| !pDRIPriv
->pSAREA
) {
2322 DRIDrvMsg(pScrn
->scrnIndex
, X_ERROR
, "[DRI] No SAREA (%p %p)\n",
2323 pDRIPriv
, pDRIPriv
? pDRIPriv
->pSAREA
: NULL
);
2327 if (pDRIPriv
->fullscreen
) {
2329 pScrn
->frameX0
= pDRIPriv
->pSAREA
->frame
.x
;
2330 pScrn
->frameY0
= pDRIPriv
->pSAREA
->frame
.y
;
2331 pScrn
->frameX1
= pScrn
->frameX0
+ pDRIPriv
->pSAREA
->frame
.width
- 1;
2332 pScrn
->frameY1
= pScrn
->frameY0
+ pDRIPriv
->pSAREA
->frame
.height
- 1;
2335 miPointerGetPosition(inputInfo
.pointer
, &px
, &py
);
2337 if (px
< pScrn
->frameX0
)
2338 px
= pScrn
->frameX0
;
2339 if (px
> pScrn
->frameX1
)
2340 px
= pScrn
->frameX1
;
2341 if (py
< pScrn
->frameY0
)
2342 py
= pScrn
->frameY0
;
2343 if (py
> pScrn
->frameY1
)
2344 py
= pScrn
->frameY1
;
2345 pScreen
->SetCursorPosition(inputInfo
.pointer
, pScreen
, px
, py
, TRUE
);
2350 if (pDRIPriv
->wrap
.AdjustFrame
) {
2352 pScrn
->AdjustFrame
= pDRIPriv
->wrap
.AdjustFrame
;
2353 /* call lower layers */
2354 (*pScrn
->AdjustFrame
) (pScrn
, x
, y
);
2356 pDRIPriv
->wrap
.AdjustFrame
= pScrn
->AdjustFrame
;
2357 pScrn
->AdjustFrame
= DRIAdjustFrame
;
2360 _DRIAdjustFrame(pScrn
, pDRIPriv
, x
, y
);
2364 * DRIMoveBuffersHelper swaps the regions rects in place leaving you
2365 * a region with the rects in the order that you need to blit them,
2366 * but it is possibly (likely) an invalid region afterwards. If you
2367 * need to use the region again for anything you have to call
2368 * REGION_VALIDATE on it, or better yet, save a copy first.
2372 DRIMoveBuffersHelper(ScreenPtr pScreen
,
2373 int dx
, int dy
, int *xdir
, int *ydir
, RegionPtr reg
)
2375 BoxPtr extents
, pbox
, firstBox
, lastBox
;
2379 extents
= RegionExtents(reg
);
2380 nbox
= RegionNumRects(reg
);
2381 pbox
= RegionRects(reg
);
2383 if ((dy
> 0) && (dy
< (extents
->y2
- extents
->y1
))) {
2387 lastBox
= pbox
+ nbox
- 1;
2388 while ((unsigned long) firstBox
< (unsigned long) lastBox
) {
2390 *firstBox
= *lastBox
;
2400 if ((dx
> 0) && (dx
< (extents
->x2
- extents
->x1
))) {
2403 firstBox
= lastBox
= pbox
;
2410 while ((unsigned long) firstBox
< (unsigned long) lastBox
) {
2412 *firstBox
= *lastBox
;
2418 firstBox
= lastBox
= pbox
;
2422 while ((unsigned long) firstBox
< (unsigned long) lastBox
) {
2424 *firstBox
= *lastBox
;
2437 DRICreatePCIBusID(const struct pci_device
*dev
)
2441 if (asprintf(&busID
, "pci:%04x:%02x:%02x.%d",
2442 dev
->domain
, dev
->bus
, dev
->dev
, dev
->func
) == -1)
2449 drmSIGIOHandler(int interrupt
, void *closure
)
2455 typedef void (*_drmCallback
) (int, void *, void *);
2462 drmHashEntry
*entry
;
2465 hash_table
= drmGetHashTable();
2469 if (drmHashFirst(hash_table
, &key
, &value
)) {
2473 fprintf(stderr
, "Trying %d\n", entry
->fd
);
2475 if ((count
= read(entry
->fd
, buf
, sizeof(buf
) - 1)) > 0) {
2478 fprintf(stderr
, "Got %s\n", buf
);
2481 for (pt
= buf
; *pt
!= ' '; ++pt
); /* Find first space */
2483 old
= strtol(pt
, &pt
, 0);
2484 new = strtol(pt
, NULL
, 0);
2485 oldctx
= drmGetContextTag(entry
->fd
, old
);
2486 newctx
= drmGetContextTag(entry
->fd
, new);
2488 fprintf(stderr
, "%d %d %p %p\n", old
, new, oldctx
, newctx
);
2490 ((_drmCallback
) entry
->f
) (entry
->fd
, oldctx
, newctx
);
2492 ioctl(entry
->fd
, DRM_IOCTL_NEW_CTX
, &ctx
);
2494 } while (drmHashNext(hash_table
, &key
, &value
));
2499 drmInstallSIGIOHandler(int fd
, void (*f
) (int, void *, void *))
2501 drmHashEntry
*entry
;
2503 entry
= drmGetEntry(fd
);
2506 return xf86InstallSIGIOHandler(fd
, drmSIGIOHandler
, 0);
2510 drmRemoveSIGIOHandler(int fd
)
2512 drmHashEntry
*entry
= drmGetEntry(fd
);
2516 return xf86RemoveSIGIOHandler(fd
);