1706f2543Smrg/************************************************************************** 2706f2543Smrg 3706f2543SmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4706f2543SmrgCopyright 2000 VA Linux Systems, Inc. 5706f2543SmrgAll Rights Reserved. 6706f2543Smrg 7706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a 8706f2543Smrgcopy of this software and associated documentation files (the 9706f2543Smrg"Software"), to deal in the Software without restriction, including 10706f2543Smrgwithout limitation the rights to use, copy, modify, merge, publish, 11706f2543Smrgdistribute, sub license, and/or sell copies of the Software, and to 12706f2543Smrgpermit persons to whom the Software is furnished to do so, subject to 13706f2543Smrgthe following conditions: 14706f2543Smrg 15706f2543SmrgThe above copyright notice and this permission notice (including the 16706f2543Smrgnext paragraph) shall be included in all copies or substantial portions 17706f2543Smrgof the Software. 18706f2543Smrg 19706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22706f2543SmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23706f2543SmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24706f2543SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25706f2543SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26706f2543Smrg 27706f2543Smrg**************************************************************************/ 28706f2543Smrg 29706f2543Smrg/* 30706f2543Smrg * Authors: 31706f2543Smrg * Jens Owen <jens@tungstengraphics.com> 32706f2543Smrg * Rickard E. (Rik) Faith <faith@valinux.com> 33706f2543Smrg * 34706f2543Smrg */ 35706f2543Smrg 36706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 37706f2543Smrg#include <xorg-config.h> 38706f2543Smrg#endif 39706f2543Smrg 40706f2543Smrg#include "xf86.h" 41706f2543Smrg#include <sys/time.h> 42706f2543Smrg#include <unistd.h> 43706f2543Smrg#include <string.h> 44706f2543Smrg#include <stdio.h> 45706f2543Smrg#include <sys/ioctl.h> 46706f2543Smrg#include <errno.h> 47706f2543Smrg 48706f2543Smrg#include <X11/X.h> 49706f2543Smrg#include <X11/Xproto.h> 50706f2543Smrg#include "xf86drm.h" 51706f2543Smrg#include "misc.h" 52706f2543Smrg#include "dixstruct.h" 53706f2543Smrg#include "extnsionst.h" 54706f2543Smrg#include "colormapst.h" 55706f2543Smrg#include "cursorstr.h" 56706f2543Smrg#include "scrnintstr.h" 57706f2543Smrg#include "windowstr.h" 58706f2543Smrg#include "servermd.h" 59706f2543Smrg#define _XF86DRI_SERVER_ 60706f2543Smrg#include <X11/dri/xf86driproto.h> 61706f2543Smrg#include "swaprep.h" 62706f2543Smrg#include "xf86str.h" 63706f2543Smrg#include "dri.h" 64706f2543Smrg#include "sarea.h" 65706f2543Smrg#include "dristruct.h" 66706f2543Smrg#include "xf86.h" 67706f2543Smrg#include "xf86drm.h" 68706f2543Smrg#include "mi.h" 69706f2543Smrg#include "mipointer.h" 70706f2543Smrg#include "xf86_OSproc.h" 71706f2543Smrg#include "inputstr.h" 72706f2543Smrg#include "xf86VGAarbiter.h" 73706f2543Smrg 74706f2543Smrgstatic int DRIEntPrivIndex = -1; 75706f2543Smrgstatic DevPrivateKeyRec DRIScreenPrivKeyRec; 76706f2543Smrg#define DRIScreenPrivKey (&DRIScreenPrivKeyRec) 77706f2543Smrgstatic DevPrivateKeyRec DRIWindowPrivKeyRec; 78706f2543Smrg#define DRIWindowPrivKey (&DRIWindowPrivKeyRec) 79706f2543Smrgstatic unsigned long DRIGeneration = 0; 80706f2543Smrgstatic unsigned int DRIDrawableValidationStamp = 0; 81706f2543Smrg 82706f2543Smrgstatic RESTYPE DRIDrawablePrivResType; 83706f2543Smrgstatic RESTYPE DRIContextPrivResType; 84706f2543Smrgstatic void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); 85706f2543Smrg 86706f2543SmrgdrmServerInfo DRIDRMServerInfo; 87706f2543Smrg 88706f2543Smrg /* Wrapper just like xf86DrvMsg, but 89706f2543Smrg without the verbosity level checking. 90706f2543Smrg This will make it easy to turn off some 91706f2543Smrg messages later, based on verbosity 92706f2543Smrg level. */ 93706f2543Smrg 94706f2543Smrg/* 95706f2543Smrg * Since we're already referencing things from the XFree86 common layer in 96706f2543Smrg * this file, we'd might as well just call xf86VDrvMsgVerb, and have 97706f2543Smrg * consistent message formatting. The verbosity of these messages can be 98706f2543Smrg * easily changed here. 99706f2543Smrg */ 100706f2543Smrg#define DRI_MSG_VERBOSITY 1 101706f2543Smrgstatic void 102706f2543SmrgDRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) 103706f2543Smrg{ 104706f2543Smrg va_list ap; 105706f2543Smrg 106706f2543Smrg va_start(ap, format); 107706f2543Smrg xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); 108706f2543Smrg va_end(ap); 109706f2543Smrg} 110706f2543Smrg 111706f2543Smrg 112706f2543Smrgstatic void 113706f2543SmrgDRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv) 114706f2543Smrg{ 115706f2543Smrg if (pDRIEntPriv->pLSAREA != NULL) { 116706f2543Smrg drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize); 117706f2543Smrg pDRIEntPriv->pLSAREA = NULL; 118706f2543Smrg } 119706f2543Smrg if (pDRIEntPriv->hLSAREA != 0) { 120706f2543Smrg drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA); 121706f2543Smrg } 122706f2543Smrg if (pDRIEntPriv->drmFD >= 0) { 123706f2543Smrg drmClose(pDRIEntPriv->drmFD); 124706f2543Smrg pDRIEntPriv->drmFD = 0; 125706f2543Smrg } 126706f2543Smrg} 127706f2543Smrg 128706f2543Smrgint 129706f2543SmrgDRIMasterFD(ScrnInfoPtr pScrn) 130706f2543Smrg{ 131706f2543Smrg return DRI_ENT_PRIV(pScrn)->drmFD; 132706f2543Smrg} 133706f2543Smrg 134706f2543Smrgvoid * 135706f2543SmrgDRIMasterSareaPointer(ScrnInfoPtr pScrn) 136706f2543Smrg{ 137706f2543Smrg return DRI_ENT_PRIV(pScrn)->pLSAREA; 138706f2543Smrg} 139706f2543Smrg 140706f2543Smrgdrm_handle_t 141706f2543SmrgDRIMasterSareaHandle(ScrnInfoPtr pScrn) 142706f2543Smrg{ 143706f2543Smrg return DRI_ENT_PRIV(pScrn)->hLSAREA; 144706f2543Smrg} 145706f2543Smrg 146706f2543Smrg 147706f2543SmrgBool 148706f2543SmrgDRIOpenDRMMaster(ScrnInfoPtr pScrn, 149706f2543Smrg unsigned long sAreaSize, 150706f2543Smrg const char *busID, 151706f2543Smrg const char *drmDriverName) 152706f2543Smrg{ 153706f2543Smrg drmSetVersion saveSv, sv; 154706f2543Smrg Bool drmWasAvailable; 155706f2543Smrg DRIEntPrivPtr pDRIEntPriv; 156706f2543Smrg DRIEntPrivRec tmp; 157706f2543Smrg drmVersionPtr drmlibv; 158706f2543Smrg int drmlibmajor, drmlibminor; 159706f2543Smrg const char *openBusID; 160706f2543Smrg int count; 161706f2543Smrg int err; 162706f2543Smrg 163706f2543Smrg if (DRIEntPrivIndex == -1) 164706f2543Smrg DRIEntPrivIndex = xf86AllocateEntityPrivateIndex(); 165706f2543Smrg 166706f2543Smrg pDRIEntPriv = DRI_ENT_PRIV(pScrn); 167706f2543Smrg 168706f2543Smrg if (pDRIEntPriv && pDRIEntPriv->drmFD != -1) 169706f2543Smrg return TRUE; 170706f2543Smrg 171706f2543Smrg drmWasAvailable = drmAvailable(); 172706f2543Smrg 173706f2543Smrg memset(&tmp, 0, sizeof(tmp)); 174706f2543Smrg 175706f2543Smrg /* Check the DRM lib version. 176706f2543Smrg * drmGetLibVersion was not supported in version 1.0, so check for 177706f2543Smrg * symbol first to avoid possible crash or hang. 178706f2543Smrg */ 179706f2543Smrg 180706f2543Smrg drmlibmajor = 1; 181706f2543Smrg drmlibminor = 0; 182706f2543Smrg if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 183706f2543Smrg drmlibv = drmGetLibVersion(-1); 184706f2543Smrg if (drmlibv != NULL) { 185706f2543Smrg drmlibmajor = drmlibv->version_major; 186706f2543Smrg drmlibminor = drmlibv->version_minor; 187706f2543Smrg drmFreeVersion(drmlibv); 188706f2543Smrg } 189706f2543Smrg } 190706f2543Smrg 191706f2543Smrg /* Check if the libdrm can handle falling back to loading based on name 192706f2543Smrg * if a busid string is passed. 193706f2543Smrg */ 194706f2543Smrg openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL; 195706f2543Smrg 196706f2543Smrg tmp.drmFD = -1; 197706f2543Smrg sv.drm_di_major = 1; 198706f2543Smrg sv.drm_di_minor = 1; 199706f2543Smrg sv.drm_dd_major = -1; 200706f2543Smrg 201706f2543Smrg saveSv = sv; 202706f2543Smrg count = 10; 203706f2543Smrg while (count--) { 204706f2543Smrg tmp.drmFD = drmOpen(drmDriverName, openBusID); 205706f2543Smrg 206706f2543Smrg if (tmp.drmFD < 0) { 207706f2543Smrg DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n"); 208706f2543Smrg goto out_err; 209706f2543Smrg } 210706f2543Smrg 211706f2543Smrg err = drmSetInterfaceVersion(tmp.drmFD, &sv); 212706f2543Smrg 213706f2543Smrg if (err != -EPERM) 214706f2543Smrg break; 215706f2543Smrg 216706f2543Smrg sv = saveSv; 217706f2543Smrg drmClose(tmp.drmFD); 218706f2543Smrg tmp.drmFD = -1; 219706f2543Smrg usleep(100000); 220706f2543Smrg } 221706f2543Smrg 222706f2543Smrg if (tmp.drmFD <= 0) { 223706f2543Smrg DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n"); 224706f2543Smrg goto out_err; 225706f2543Smrg } 226706f2543Smrg 227706f2543Smrg if (!drmWasAvailable) { 228706f2543Smrg DRIDrvMsg(-1, X_INFO, 229706f2543Smrg "[drm] loaded kernel module for \"%s\" driver.\n", 230706f2543Smrg drmDriverName); 231706f2543Smrg } 232706f2543Smrg 233706f2543Smrg if (err != 0) { 234706f2543Smrg sv.drm_di_major = 1; 235706f2543Smrg sv.drm_di_minor = 0; 236706f2543Smrg } 237706f2543Smrg 238706f2543Smrg DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n", 239706f2543Smrg sv.drm_di_major, sv.drm_di_minor); 240706f2543Smrg 241706f2543Smrg if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1) 242706f2543Smrg err = 0; 243706f2543Smrg else 244706f2543Smrg err = drmSetBusid(tmp.drmFD, busID); 245706f2543Smrg 246706f2543Smrg if (err) { 247706f2543Smrg DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n"); 248706f2543Smrg goto out_err; 249706f2543Smrg } 250706f2543Smrg 251706f2543Smrg /* 252706f2543Smrg * Create a lock-containing sarea. 253706f2543Smrg */ 254706f2543Smrg 255706f2543Smrg if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM, 256706f2543Smrg DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) { 257706f2543Smrg DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n"); 258706f2543Smrg tmp.hLSAREA = 0; 259706f2543Smrg goto out_err; 260706f2543Smrg } 261706f2543Smrg 262706f2543Smrg if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize, 263706f2543Smrg (drmAddressPtr)(&tmp.pLSAREA)) < 0) { 264706f2543Smrg DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n"); 265706f2543Smrg tmp.pLSAREA = NULL; 266706f2543Smrg goto out_err; 267706f2543Smrg } 268706f2543Smrg 269706f2543Smrg memset(tmp.pLSAREA, 0, sAreaSize); 270706f2543Smrg 271706f2543Smrg /* 272706f2543Smrg * Reserved contexts are handled by the first opened screen. 273706f2543Smrg */ 274706f2543Smrg 275706f2543Smrg tmp.resOwner = NULL; 276706f2543Smrg 277706f2543Smrg if (!pDRIEntPriv) 278706f2543Smrg pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1); 279706f2543Smrg 280706f2543Smrg if (!pDRIEntPriv) { 281706f2543Smrg DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for " 282706f2543Smrg "DRM device.\n"); 283706f2543Smrg goto out_err; 284706f2543Smrg } 285706f2543Smrg *pDRIEntPriv = tmp; 286706f2543Smrg xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr = 287706f2543Smrg pDRIEntPriv; 288706f2543Smrg 289706f2543Smrg DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n"); 290706f2543Smrg return TRUE; 291706f2543Smrg 292706f2543Smrg out_err: 293706f2543Smrg 294706f2543Smrg DRIOpenDRMCleanup(&tmp); 295706f2543Smrg return FALSE; 296706f2543Smrg} 297706f2543Smrg 298706f2543Smrgstatic void 299706f2543SmrgDRIClipNotifyAllDrawables(ScreenPtr pScreen); 300706f2543Smrg 301706f2543Smrgstatic void 302706f2543Smrgdri_crtc_notify(ScreenPtr pScreen) 303706f2543Smrg{ 304706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 305706f2543Smrg DRIClipNotifyAllDrawables(pScreen); 306706f2543Smrg xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); 307706f2543Smrg xf86_crtc_notify(pScreen); 308706f2543Smrg pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify); 309706f2543Smrg} 310706f2543Smrg 311706f2543SmrgBool 312706f2543SmrgDRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) 313706f2543Smrg{ 314706f2543Smrg DRIScreenPrivPtr pDRIPriv; 315706f2543Smrg drm_context_t * reserved; 316706f2543Smrg int reserved_count; 317706f2543Smrg int i; 318706f2543Smrg DRIEntPrivPtr pDRIEntPriv; 319706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 320706f2543Smrg DRIContextFlags flags = 0; 321706f2543Smrg DRIContextPrivPtr pDRIContextPriv; 322706f2543Smrg 323706f2543Smrg /* If the DRI extension is disabled, do not initialize the DRI */ 324706f2543Smrg if (noXFree86DRIExtension) { 325706f2543Smrg DRIDrvMsg(pScreen->myNum, X_WARNING, 326706f2543Smrg "Direct rendering has been disabled.\n"); 327706f2543Smrg return FALSE; 328706f2543Smrg } 329706f2543Smrg 330706f2543Smrg if (!xf86VGAarbiterAllowDRI(pScreen)) { 331706f2543Smrg DRIDrvMsg(pScreen->myNum, X_WARNING, 332706f2543Smrg "Direct rendering is not supported when VGA arb is necessary for the device\n"); 333706f2543Smrg return FALSE; 334706f2543Smrg } 335706f2543Smrg 336706f2543Smrg#ifdef PANORAMIX 337706f2543Smrg /* 338706f2543Smrg * If Xinerama is on, don't allow DRI to initialise. It won't be usable 339706f2543Smrg * anyway. 340706f2543Smrg */ 341706f2543Smrg if (!noPanoramiXExtension) { 342706f2543Smrg DRIDrvMsg(pScreen->myNum, X_WARNING, 343706f2543Smrg "Direct rendering is not supported when Xinerama is enabled\n"); 344706f2543Smrg return FALSE; 345706f2543Smrg } 346706f2543Smrg#endif 347706f2543Smrg 348706f2543Smrg if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize, 349706f2543Smrg pDRIInfo->busIdString, 350706f2543Smrg pDRIInfo->drmDriverName)) 351706f2543Smrg return FALSE; 352706f2543Smrg 353706f2543Smrg pDRIEntPriv = DRI_ENT_PRIV(pScrn); 354706f2543Smrg 355706f2543Smrg if (DRIGeneration != serverGeneration) 356706f2543Smrg DRIGeneration = serverGeneration; 357706f2543Smrg 358706f2543Smrg if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0)) 359706f2543Smrg return FALSE; 360706f2543Smrg if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0)) 361706f2543Smrg return FALSE; 362706f2543Smrg 363706f2543Smrg pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); 364706f2543Smrg if (!pDRIPriv) { 365706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 366706f2543Smrg return FALSE; 367706f2543Smrg } 368706f2543Smrg 369706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); 370706f2543Smrg pDRIPriv->drmFD = pDRIEntPriv->drmFD; 371706f2543Smrg pDRIPriv->directRenderingSupport = TRUE; 372706f2543Smrg pDRIPriv->pDriverInfo = pDRIInfo; 373706f2543Smrg pDRIPriv->nrWindows = 0; 374706f2543Smrg pDRIPriv->nrWindowsVisible = 0; 375706f2543Smrg pDRIPriv->fullscreen = NULL; 376706f2543Smrg 377706f2543Smrg pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; 378706f2543Smrg pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; 379706f2543Smrg 380706f2543Smrg pDRIPriv->grabbedDRILock = FALSE; 381706f2543Smrg pDRIPriv->drmSIGIOHandlerInstalled = FALSE; 382706f2543Smrg *pDRMFD = pDRIPriv->drmFD; 383706f2543Smrg 384706f2543Smrg if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) { 385706f2543Smrg 386706f2543Smrg if (drmAddMap( pDRIPriv->drmFD, 387706f2543Smrg 0, 388706f2543Smrg pDRIPriv->pDriverInfo->SAREASize, 389706f2543Smrg DRM_SHM, 390706f2543Smrg 0, 391706f2543Smrg &pDRIPriv->hSAREA) < 0) 392706f2543Smrg { 393706f2543Smrg pDRIPriv->directRenderingSupport = FALSE; 394706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 395706f2543Smrg drmClose(pDRIPriv->drmFD); 396706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 397706f2543Smrg "[drm] drmAddMap failed\n"); 398706f2543Smrg return FALSE; 399706f2543Smrg } 400706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 401706f2543Smrg "[drm] added %d byte SAREA at %p\n", 402706f2543Smrg pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA); 403706f2543Smrg 404706f2543Smrg /* Backwards compat. */ 405706f2543Smrg if (drmMap( pDRIPriv->drmFD, 406706f2543Smrg pDRIPriv->hSAREA, 407706f2543Smrg pDRIPriv->pDriverInfo->SAREASize, 408706f2543Smrg (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) 409706f2543Smrg { 410706f2543Smrg pDRIPriv->directRenderingSupport = FALSE; 411706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 412706f2543Smrg drmClose(pDRIPriv->drmFD); 413706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 414706f2543Smrg "[drm] drmMap failed\n"); 415706f2543Smrg return FALSE; 416706f2543Smrg } 417706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", 418706f2543Smrg pDRIPriv->hSAREA, pDRIPriv->pSAREA); 419706f2543Smrg memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); 420706f2543Smrg } else { 421706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock " 422706f2543Smrg "SAREA also for drawables.\n"); 423706f2543Smrg pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA; 424706f2543Smrg pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA; 425706f2543Smrg pDRIEntPriv->sAreaGrabbed = TRUE; 426706f2543Smrg } 427706f2543Smrg 428706f2543Smrg pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA; 429706f2543Smrg pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA; 430706f2543Smrg 431706f2543Smrg if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer) 432706f2543Smrg { 433706f2543Smrg if (drmAddMap( pDRIPriv->drmFD, 434706f2543Smrg (uintptr_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress, 435706f2543Smrg pDRIPriv->pDriverInfo->frameBufferSize, 436706f2543Smrg DRM_FRAME_BUFFER, 437706f2543Smrg 0, 438706f2543Smrg &pDRIPriv->pDriverInfo->hFrameBuffer) < 0) 439706f2543Smrg { 440706f2543Smrg pDRIPriv->directRenderingSupport = FALSE; 441706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 442706f2543Smrg drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); 443706f2543Smrg drmClose(pDRIPriv->drmFD); 444706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 445706f2543Smrg "[drm] drmAddMap failed\n"); 446706f2543Smrg return FALSE; 447706f2543Smrg } 448706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", 449706f2543Smrg pDRIPriv->pDriverInfo->hFrameBuffer); 450706f2543Smrg } else { 451706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 452706f2543Smrg "[drm] framebuffer mapped by ddx driver\n"); 453706f2543Smrg } 454706f2543Smrg 455706f2543Smrg if (pDRIEntPriv->resOwner == NULL) { 456706f2543Smrg pDRIEntPriv->resOwner = pScreen; 457706f2543Smrg 458706f2543Smrg /* Add tags for reserved contexts */ 459706f2543Smrg if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, 460706f2543Smrg &reserved_count))) { 461706f2543Smrg int i; 462706f2543Smrg void *tag; 463706f2543Smrg 464706f2543Smrg for (i = 0; i < reserved_count; i++) { 465706f2543Smrg tag = DRICreateContextPrivFromHandle(pScreen, 466706f2543Smrg reserved[i], 467706f2543Smrg DRI_CONTEXT_RESERVED); 468706f2543Smrg drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag); 469706f2543Smrg } 470706f2543Smrg drmFreeReservedContextList(reserved); 471706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 472706f2543Smrg "[drm] added %d reserved context%s for kernel\n", 473706f2543Smrg reserved_count, reserved_count > 1 ? "s" : ""); 474706f2543Smrg } 475706f2543Smrg } 476706f2543Smrg 477706f2543Smrg /* validate max drawable table entry set by driver */ 478706f2543Smrg if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || 479706f2543Smrg (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { 480706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 481706f2543Smrg "Invalid max drawable table size set by driver: %d\n", 482706f2543Smrg pDRIPriv->pDriverInfo->maxDrawableTableEntry); 483706f2543Smrg } 484706f2543Smrg 485706f2543Smrg /* Initialize drawable tables (screen private and SAREA) */ 486706f2543Smrg for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { 487706f2543Smrg pDRIPriv->DRIDrawables[i] = NULL; 488706f2543Smrg pDRIPriv->pSAREA->drawableTable[i].stamp = 0; 489706f2543Smrg pDRIPriv->pSAREA->drawableTable[i].flags = 0; 490706f2543Smrg } 491706f2543Smrg 492706f2543Smrg pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount; 493706f2543Smrg pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext; 494706f2543Smrg 495706f2543Smrg if (!pDRIEntPriv->keepFDOpen) 496706f2543Smrg pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen; 497706f2543Smrg 498706f2543Smrg pDRIEntPriv->refCount++; 499706f2543Smrg 500706f2543Smrg /* Set up flags for DRICreateContextPriv */ 501706f2543Smrg switch (pDRIInfo->driverSwapMethod) { 502706f2543Smrg case DRI_KERNEL_SWAP: 503706f2543Smrg flags = DRI_CONTEXT_2DONLY; 504706f2543Smrg break; 505706f2543Smrg case DRI_HIDE_X_CONTEXT: 506706f2543Smrg flags = DRI_CONTEXT_PRESERVED; 507706f2543Smrg break; 508706f2543Smrg } 509706f2543Smrg 510706f2543Smrg if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, 511706f2543Smrg &pDRIPriv->myContext, 512706f2543Smrg flags))) { 513706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 514706f2543Smrg "failed to create server context\n"); 515706f2543Smrg return FALSE; 516706f2543Smrg } 517706f2543Smrg pDRIPriv->myContextPriv = pDRIContextPriv; 518706f2543Smrg 519706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 520706f2543Smrg "X context handle = %p\n", pDRIPriv->myContext); 521706f2543Smrg 522706f2543Smrg /* Now that we have created the X server's context, we can grab the 523706f2543Smrg * hardware lock for the X server. 524706f2543Smrg */ 525706f2543Smrg DRILock(pScreen, 0); 526706f2543Smrg pDRIPriv->grabbedDRILock = TRUE; 527706f2543Smrg 528706f2543Smrg /* pointers so that we can prevent memory leaks later */ 529706f2543Smrg pDRIPriv->hiddenContextStore = NULL; 530706f2543Smrg pDRIPriv->partial3DContextStore = NULL; 531706f2543Smrg 532706f2543Smrg switch(pDRIInfo->driverSwapMethod) { 533706f2543Smrg case DRI_HIDE_X_CONTEXT: 534706f2543Smrg /* Server will handle 3D swaps, and hide 2D swaps from kernel. 535706f2543Smrg * Register server context as a preserved context. 536706f2543Smrg */ 537706f2543Smrg 538706f2543Smrg /* allocate memory for hidden context store */ 539706f2543Smrg pDRIPriv->hiddenContextStore 540706f2543Smrg = (void *)calloc(1, pDRIInfo->contextSize); 541706f2543Smrg if (!pDRIPriv->hiddenContextStore) { 542706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 543706f2543Smrg "failed to allocate hidden context\n"); 544706f2543Smrg DRIDestroyContextPriv(pDRIContextPriv); 545706f2543Smrg return FALSE; 546706f2543Smrg } 547706f2543Smrg 548706f2543Smrg /* allocate memory for partial 3D context store */ 549706f2543Smrg pDRIPriv->partial3DContextStore 550706f2543Smrg = (void *)calloc(1, pDRIInfo->contextSize); 551706f2543Smrg if (!pDRIPriv->partial3DContextStore) { 552706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 553706f2543Smrg "[DRI] failed to allocate partial 3D context\n"); 554706f2543Smrg free(pDRIPriv->hiddenContextStore); 555706f2543Smrg DRIDestroyContextPriv(pDRIContextPriv); 556706f2543Smrg return FALSE; 557706f2543Smrg } 558706f2543Smrg 559706f2543Smrg /* save initial context store */ 560706f2543Smrg if (pDRIInfo->SwapContext) { 561706f2543Smrg (*pDRIInfo->SwapContext)( 562706f2543Smrg pScreen, 563706f2543Smrg DRI_NO_SYNC, 564706f2543Smrg DRI_2D_CONTEXT, 565706f2543Smrg pDRIPriv->hiddenContextStore, 566706f2543Smrg DRI_NO_CONTEXT, 567706f2543Smrg NULL); 568706f2543Smrg } 569706f2543Smrg /* fall through */ 570706f2543Smrg 571706f2543Smrg case DRI_SERVER_SWAP: 572706f2543Smrg /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT 573706f2543Smrg * setup signal handler for receiving swap requests from kernel 574706f2543Smrg */ 575706f2543Smrg if (!(pDRIPriv->drmSIGIOHandlerInstalled = 576706f2543Smrg drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { 577706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 578706f2543Smrg "[drm] failed to setup DRM signal handler\n"); 579706f2543Smrg free(pDRIPriv->hiddenContextStore); 580706f2543Smrg free(pDRIPriv->partial3DContextStore); 581706f2543Smrg DRIDestroyContextPriv(pDRIContextPriv); 582706f2543Smrg return FALSE; 583706f2543Smrg } else { 584706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 585706f2543Smrg "[drm] installed DRM signal handler\n"); 586706f2543Smrg } 587706f2543Smrg 588706f2543Smrg default: 589706f2543Smrg break; 590706f2543Smrg } 591706f2543Smrg 592706f2543Smrg return TRUE; 593706f2543Smrg} 594706f2543Smrg 595706f2543SmrgBool 596706f2543SmrgDRIFinishScreenInit(ScreenPtr pScreen) 597706f2543Smrg{ 598706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 599706f2543Smrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 600706f2543Smrg 601706f2543Smrg /* Wrap DRI support */ 602706f2543Smrg if (pDRIInfo->wrap.ValidateTree) { 603706f2543Smrg pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 604706f2543Smrg pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree; 605706f2543Smrg } 606706f2543Smrg if (pDRIInfo->wrap.PostValidateTree) { 607706f2543Smrg pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 608706f2543Smrg pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree; 609706f2543Smrg } 610706f2543Smrg if (pDRIInfo->wrap.WindowExposures) { 611706f2543Smrg pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 612706f2543Smrg pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; 613706f2543Smrg } 614706f2543Smrg 615706f2543Smrg pDRIPriv->DestroyWindow = pScreen->DestroyWindow; 616706f2543Smrg pScreen->DestroyWindow = DRIDestroyWindow; 617706f2543Smrg 618706f2543Smrg pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, 619706f2543Smrg dri_crtc_notify); 620706f2543Smrg 621706f2543Smrg if (pDRIInfo->wrap.CopyWindow) { 622706f2543Smrg pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 623706f2543Smrg pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; 624706f2543Smrg } 625706f2543Smrg if (pDRIInfo->wrap.ClipNotify) { 626706f2543Smrg pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 627706f2543Smrg pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; 628706f2543Smrg } 629706f2543Smrg if (pDRIInfo->wrap.AdjustFrame) { 630706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 631706f2543Smrg pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; 632706f2543Smrg pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; 633706f2543Smrg } 634706f2543Smrg pDRIPriv->wrapped = TRUE; 635706f2543Smrg 636706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); 637706f2543Smrg 638706f2543Smrg return TRUE; 639706f2543Smrg} 640706f2543Smrg 641706f2543Smrgvoid 642706f2543SmrgDRICloseScreen(ScreenPtr pScreen) 643706f2543Smrg{ 644706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 645706f2543Smrg DRIInfoPtr pDRIInfo; 646706f2543Smrg drm_context_t * reserved; 647706f2543Smrg int reserved_count; 648706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 649706f2543Smrg DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn); 650706f2543Smrg Bool closeMaster; 651706f2543Smrg 652706f2543Smrg if (pDRIPriv) { 653706f2543Smrg 654706f2543Smrg pDRIInfo = pDRIPriv->pDriverInfo; 655706f2543Smrg 656706f2543Smrg if (pDRIPriv->wrapped) { 657706f2543Smrg /* Unwrap DRI Functions */ 658706f2543Smrg if (pDRIInfo->wrap.ValidateTree) { 659706f2543Smrg pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; 660706f2543Smrg pDRIPriv->wrap.ValidateTree = NULL; 661706f2543Smrg } 662706f2543Smrg if (pDRIInfo->wrap.PostValidateTree) { 663706f2543Smrg pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; 664706f2543Smrg pDRIPriv->wrap.PostValidateTree = NULL; 665706f2543Smrg } 666706f2543Smrg if (pDRIInfo->wrap.WindowExposures) { 667706f2543Smrg pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 668706f2543Smrg pDRIPriv->wrap.WindowExposures = NULL; 669706f2543Smrg } 670706f2543Smrg if (pDRIPriv->DestroyWindow) { 671706f2543Smrg pScreen->DestroyWindow = pDRIPriv->DestroyWindow; 672706f2543Smrg pDRIPriv->DestroyWindow = NULL; 673706f2543Smrg } 674706f2543Smrg 675706f2543Smrg xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); 676706f2543Smrg 677706f2543Smrg if (pDRIInfo->wrap.CopyWindow) { 678706f2543Smrg pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 679706f2543Smrg pDRIPriv->wrap.CopyWindow = NULL; 680706f2543Smrg } 681706f2543Smrg if (pDRIInfo->wrap.ClipNotify) { 682706f2543Smrg pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 683706f2543Smrg pDRIPriv->wrap.ClipNotify = NULL; 684706f2543Smrg } 685706f2543Smrg if (pDRIInfo->wrap.AdjustFrame) { 686706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 687706f2543Smrg pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; 688706f2543Smrg pDRIPriv->wrap.AdjustFrame = NULL; 689706f2543Smrg } 690706f2543Smrg 691706f2543Smrg pDRIPriv->wrapped = FALSE; 692706f2543Smrg } 693706f2543Smrg 694706f2543Smrg if (pDRIPriv->drmSIGIOHandlerInstalled) { 695706f2543Smrg if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { 696706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 697706f2543Smrg "[drm] failed to remove DRM signal handler\n"); 698706f2543Smrg } 699706f2543Smrg } 700706f2543Smrg 701706f2543Smrg if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { 702706f2543Smrg DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); 703706f2543Smrg } 704706f2543Smrg 705706f2543Smrg if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { 706706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 707706f2543Smrg "failed to destroy server context\n"); 708706f2543Smrg } 709706f2543Smrg 710706f2543Smrg /* Remove tags for reserved contexts */ 711706f2543Smrg if (pDRIEntPriv->resOwner == pScreen) { 712706f2543Smrg pDRIEntPriv->resOwner = NULL; 713706f2543Smrg 714706f2543Smrg if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, 715706f2543Smrg &reserved_count))) { 716706f2543Smrg int i; 717706f2543Smrg 718706f2543Smrg for (i = 0; i < reserved_count; i++) { 719706f2543Smrg DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, 720706f2543Smrg reserved[i])); 721706f2543Smrg } 722706f2543Smrg drmFreeReservedContextList(reserved); 723706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 724706f2543Smrg "[drm] removed %d reserved context%s for kernel\n", 725706f2543Smrg reserved_count, reserved_count > 1 ? "s" : ""); 726706f2543Smrg } 727706f2543Smrg } 728706f2543Smrg 729706f2543Smrg /* Make sure signals get unblocked etc. */ 730706f2543Smrg drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); 731706f2543Smrg pDRIPriv->pLockRefCount = NULL; 732706f2543Smrg closeMaster = (--pDRIEntPriv->refCount == 0) && 733706f2543Smrg !pDRIEntPriv->keepFDOpen; 734706f2543Smrg if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) { 735706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 736706f2543Smrg "[drm] unmapping %d bytes of SAREA %p at %p\n", 737706f2543Smrg pDRIInfo->SAREASize, 738706f2543Smrg pDRIPriv->hSAREA, 739706f2543Smrg pDRIPriv->pSAREA); 740706f2543Smrg if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { 741706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 742706f2543Smrg "[drm] unable to unmap %d bytes" 743706f2543Smrg " of SAREA %p at %p\n", 744706f2543Smrg pDRIInfo->SAREASize, 745706f2543Smrg pDRIPriv->hSAREA, 746706f2543Smrg pDRIPriv->pSAREA); 747706f2543Smrg } 748706f2543Smrg } else { 749706f2543Smrg pDRIEntPriv->sAreaGrabbed = FALSE; 750706f2543Smrg } 751706f2543Smrg 752706f2543Smrg if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) { 753706f2543Smrg drmClose(pDRIPriv->drmFD); 754706f2543Smrg if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) { 755706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 756706f2543Smrg "[drm] Closed DRM master.\n"); 757706f2543Smrg pDRIEntPriv->drmFD = -1; 758706f2543Smrg } 759706f2543Smrg } 760706f2543Smrg 761706f2543Smrg free(pDRIPriv); 762706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 763706f2543Smrg } 764706f2543Smrg} 765706f2543Smrg 766706f2543Smrg#define DRM_MSG_VERBOSITY 3 767706f2543Smrg 768706f2543Smrgstatic int dri_drm_debug_print(const char *format, va_list ap) 769706f2543Smrg{ 770706f2543Smrg xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); 771706f2543Smrg return 0; 772706f2543Smrg} 773706f2543Smrg 774706f2543Smrgstatic void dri_drm_get_perms(gid_t *group, mode_t *mode) 775706f2543Smrg{ 776706f2543Smrg *group = xf86ConfigDRI.group; 777706f2543Smrg *mode = xf86ConfigDRI.mode; 778706f2543Smrg} 779706f2543Smrg 780706f2543SmrgdrmServerInfo DRIDRMServerInfo = { 781706f2543Smrg dri_drm_debug_print, 782706f2543Smrg xf86LoadKernelModule, 783706f2543Smrg dri_drm_get_perms, 784706f2543Smrg}; 785706f2543Smrg 786706f2543SmrgBool 787706f2543SmrgDRIExtensionInit(void) 788706f2543Smrg{ 789706f2543Smrg if (DRIGeneration != serverGeneration) { 790706f2543Smrg return FALSE; 791706f2543Smrg } 792706f2543Smrg 793706f2543Smrg DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, 794706f2543Smrg "DRIDrawable"); 795706f2543Smrg DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete, 796706f2543Smrg "DRIContext"); 797706f2543Smrg 798706f2543Smrg if (!DRIDrawablePrivResType || !DRIContextPrivResType) 799706f2543Smrg return FALSE; 800706f2543Smrg 801706f2543Smrg RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); 802706f2543Smrg 803706f2543Smrg return TRUE; 804706f2543Smrg} 805706f2543Smrg 806706f2543Smrgvoid 807706f2543SmrgDRIReset(void) 808706f2543Smrg{ 809706f2543Smrg /* 810706f2543Smrg * This stub routine is called when the X Server recycles, resources 811706f2543Smrg * allocated by DRIExtensionInit need to be managed here. 812706f2543Smrg * 813706f2543Smrg * Currently this routine is a stub because all the interesting resources 814706f2543Smrg * are managed via the screen init process. 815706f2543Smrg */ 816706f2543Smrg} 817706f2543Smrg 818706f2543SmrgBool 819706f2543SmrgDRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) 820706f2543Smrg{ 821706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 822706f2543Smrg 823706f2543Smrg if (pDRIPriv) 824706f2543Smrg *isCapable = pDRIPriv->directRenderingSupport; 825706f2543Smrg else 826706f2543Smrg *isCapable = FALSE; 827706f2543Smrg 828706f2543Smrg return TRUE; 829706f2543Smrg} 830706f2543Smrg 831706f2543SmrgBool 832706f2543SmrgDRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) 833706f2543Smrg{ 834706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 835706f2543Smrg 836706f2543Smrg *hSAREA = pDRIPriv->hSAREA; 837706f2543Smrg *busIdString = pDRIPriv->pDriverInfo->busIdString; 838706f2543Smrg 839706f2543Smrg return TRUE; 840706f2543Smrg} 841706f2543Smrg 842706f2543SmrgBool 843706f2543SmrgDRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) 844706f2543Smrg{ 845706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 846706f2543Smrg 847706f2543Smrg if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; 848706f2543Smrg return TRUE; 849706f2543Smrg} 850706f2543Smrg 851706f2543SmrgBool 852706f2543SmrgDRICloseConnection(ScreenPtr pScreen) 853706f2543Smrg{ 854706f2543Smrg return TRUE; 855706f2543Smrg} 856706f2543Smrg 857706f2543SmrgBool 858706f2543SmrgDRIGetClientDriverName(ScreenPtr pScreen, 859706f2543Smrg int *ddxDriverMajorVersion, 860706f2543Smrg int *ddxDriverMinorVersion, 861706f2543Smrg int *ddxDriverPatchVersion, 862706f2543Smrg char **clientDriverName) 863706f2543Smrg{ 864706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 865706f2543Smrg 866706f2543Smrg *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; 867706f2543Smrg *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; 868706f2543Smrg *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; 869706f2543Smrg *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; 870706f2543Smrg 871706f2543Smrg return TRUE; 872706f2543Smrg} 873706f2543Smrg 874706f2543Smrg/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper 875706f2543Smrg functions that layer on drmCreateContext and drmAddContextTag. 876706f2543Smrg 877706f2543Smrg DRICreateContextPriv always creates a kernel drm_context_t and then calls 878706f2543Smrg DRICreateContextPrivFromHandle to create a DRIContextPriv structure for 879706f2543Smrg DRI tracking. For the SIGIO handler, the drm_context_t is associated with 880706f2543Smrg DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv 881706f2543Smrg area and are passed to the kernel (if necessary). 882706f2543Smrg 883706f2543Smrg DRICreateContextPriv returns a pointer to newly allocated 884706f2543Smrg DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ 885706f2543Smrg 886706f2543SmrgDRIContextPrivPtr 887706f2543SmrgDRICreateContextPriv(ScreenPtr pScreen, 888706f2543Smrg drm_context_t * pHWContext, 889706f2543Smrg DRIContextFlags flags) 890706f2543Smrg{ 891706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 892706f2543Smrg 893706f2543Smrg if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { 894706f2543Smrg return NULL; 895706f2543Smrg } 896706f2543Smrg 897706f2543Smrg return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); 898706f2543Smrg} 899706f2543Smrg 900706f2543SmrgDRIContextPrivPtr 901706f2543SmrgDRICreateContextPrivFromHandle(ScreenPtr pScreen, 902706f2543Smrg drm_context_t hHWContext, 903706f2543Smrg DRIContextFlags flags) 904706f2543Smrg{ 905706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 906706f2543Smrg DRIContextPrivPtr pDRIContextPriv; 907706f2543Smrg int contextPrivSize; 908706f2543Smrg 909706f2543Smrg contextPrivSize = sizeof(DRIContextPrivRec) + 910706f2543Smrg pDRIPriv->pDriverInfo->contextSize; 911706f2543Smrg if (!(pDRIContextPriv = calloc(1, contextPrivSize))) { 912706f2543Smrg return NULL; 913706f2543Smrg } 914706f2543Smrg pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1); 915706f2543Smrg 916706f2543Smrg drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); 917706f2543Smrg 918706f2543Smrg pDRIContextPriv->hwContext = hHWContext; 919706f2543Smrg pDRIContextPriv->pScreen = pScreen; 920706f2543Smrg pDRIContextPriv->flags = flags; 921706f2543Smrg pDRIContextPriv->valid3D = FALSE; 922706f2543Smrg 923706f2543Smrg if (flags & DRI_CONTEXT_2DONLY) { 924706f2543Smrg if (drmSetContextFlags(pDRIPriv->drmFD, 925706f2543Smrg hHWContext, 926706f2543Smrg DRM_CONTEXT_2DONLY)) { 927706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 928706f2543Smrg "[drm] failed to set 2D context flag\n"); 929706f2543Smrg DRIDestroyContextPriv(pDRIContextPriv); 930706f2543Smrg return NULL; 931706f2543Smrg } 932706f2543Smrg } 933706f2543Smrg if (flags & DRI_CONTEXT_PRESERVED) { 934706f2543Smrg if (drmSetContextFlags(pDRIPriv->drmFD, 935706f2543Smrg hHWContext, 936706f2543Smrg DRM_CONTEXT_PRESERVED)) { 937706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 938706f2543Smrg "[drm] failed to set preserved flag\n"); 939706f2543Smrg DRIDestroyContextPriv(pDRIContextPriv); 940706f2543Smrg return NULL; 941706f2543Smrg } 942706f2543Smrg } 943706f2543Smrg return pDRIContextPriv; 944706f2543Smrg} 945706f2543Smrg 946706f2543SmrgBool 947706f2543SmrgDRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) 948706f2543Smrg{ 949706f2543Smrg DRIScreenPrivPtr pDRIPriv; 950706f2543Smrg 951706f2543Smrg if (!pDRIContextPriv) return TRUE; 952706f2543Smrg 953706f2543Smrg pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); 954706f2543Smrg 955706f2543Smrg if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { 956706f2543Smrg /* Don't delete reserved contexts from 957706f2543Smrg kernel area -- the kernel manages its 958706f2543Smrg reserved contexts itself. */ 959706f2543Smrg if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) 960706f2543Smrg return FALSE; 961706f2543Smrg } 962706f2543Smrg 963706f2543Smrg /* Remove the tag last to prevent a race 964706f2543Smrg condition where the context has pending 965706f2543Smrg buffers. The context can't be re-used 966706f2543Smrg while in this thread, but buffers can be 967706f2543Smrg dispatched asynchronously. */ 968706f2543Smrg drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); 969706f2543Smrg free(pDRIContextPriv); 970706f2543Smrg return TRUE; 971706f2543Smrg} 972706f2543Smrg 973706f2543Smrgstatic Bool 974706f2543SmrgDRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) 975706f2543Smrg{ 976706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 977706f2543Smrg DRIContextPrivPtr pDRIContextPriv; 978706f2543Smrg void *contextStore; 979706f2543Smrg 980706f2543Smrg if (!(pDRIContextPriv = 981706f2543Smrg DRICreateContextPriv(pScreen, 982706f2543Smrg &pDRIPriv->pSAREA->dummy_context, 0))) { 983706f2543Smrg return FALSE; 984706f2543Smrg } 985706f2543Smrg 986706f2543Smrg contextStore = DRIGetContextStore(pDRIContextPriv); 987706f2543Smrg if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { 988706f2543Smrg if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL, 989706f2543Smrg pDRIPriv->pSAREA->dummy_context, 990706f2543Smrg NULL, 991706f2543Smrg (DRIContextType)(long)contextStore)) { 992706f2543Smrg DRIDestroyContextPriv(pDRIContextPriv); 993706f2543Smrg return FALSE; 994706f2543Smrg } 995706f2543Smrg } 996706f2543Smrg 997706f2543Smrg pDRIPriv->dummyCtxPriv = pDRIContextPriv; 998706f2543Smrg return TRUE; 999706f2543Smrg} 1000706f2543Smrg 1001706f2543Smrgstatic void 1002706f2543SmrgDRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) 1003706f2543Smrg{ 1004706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1005706f2543Smrg DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; 1006706f2543Smrg void *contextStore; 1007706f2543Smrg 1008706f2543Smrg if (!pDRIContextPriv) return; 1009706f2543Smrg if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { 1010706f2543Smrg contextStore = DRIGetContextStore(pDRIContextPriv); 1011706f2543Smrg pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, 1012706f2543Smrg pDRIContextPriv->hwContext, 1013706f2543Smrg (DRIContextType)(long)contextStore); 1014706f2543Smrg } 1015706f2543Smrg 1016706f2543Smrg DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); 1017706f2543Smrg pDRIPriv->dummyCtxPriv = NULL; 1018706f2543Smrg} 1019706f2543Smrg 1020706f2543SmrgBool 1021706f2543SmrgDRICreateContext(ScreenPtr pScreen, VisualPtr visual, 1022706f2543Smrg XID context, drm_context_t * pHWContext) 1023706f2543Smrg{ 1024706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1025706f2543Smrg DRIContextPrivPtr pDRIContextPriv; 1026706f2543Smrg void *contextStore; 1027706f2543Smrg 1028706f2543Smrg if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { 1029706f2543Smrg if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { 1030706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 1031706f2543Smrg "[drm] Could not create dummy context\n"); 1032706f2543Smrg return FALSE; 1033706f2543Smrg } 1034706f2543Smrg } 1035706f2543Smrg 1036706f2543Smrg if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { 1037706f2543Smrg return FALSE; 1038706f2543Smrg } 1039706f2543Smrg 1040706f2543Smrg contextStore = DRIGetContextStore(pDRIContextPriv); 1041706f2543Smrg if (pDRIPriv->pDriverInfo->CreateContext) { 1042706f2543Smrg if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL, 1043706f2543Smrg *pHWContext, NULL, 1044706f2543Smrg (DRIContextType)(long)contextStore))) { 1045706f2543Smrg DRIDestroyContextPriv(pDRIContextPriv); 1046706f2543Smrg return FALSE; 1047706f2543Smrg } 1048706f2543Smrg } 1049706f2543Smrg 1050706f2543Smrg /* track this in case the client dies before cleanup */ 1051706f2543Smrg AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv); 1052706f2543Smrg 1053706f2543Smrg return TRUE; 1054706f2543Smrg} 1055706f2543Smrg 1056706f2543SmrgBool 1057706f2543SmrgDRIDestroyContext(ScreenPtr pScreen, XID context) 1058706f2543Smrg{ 1059706f2543Smrg FreeResourceByType(context, DRIContextPrivResType, FALSE); 1060706f2543Smrg 1061706f2543Smrg return TRUE; 1062706f2543Smrg} 1063706f2543Smrg 1064706f2543Smrg/* DRIContextPrivDelete is called by the resource manager. */ 1065706f2543SmrgBool 1066706f2543SmrgDRIContextPrivDelete(pointer pResource, XID id) 1067706f2543Smrg{ 1068706f2543Smrg DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource; 1069706f2543Smrg DRIScreenPrivPtr pDRIPriv; 1070706f2543Smrg void *contextStore; 1071706f2543Smrg 1072706f2543Smrg pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); 1073706f2543Smrg if (pDRIPriv->pDriverInfo->DestroyContext) { 1074706f2543Smrg contextStore = DRIGetContextStore(pDRIContextPriv); 1075706f2543Smrg pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, 1076706f2543Smrg pDRIContextPriv->hwContext, 1077706f2543Smrg (DRIContextType)(long)contextStore); 1078706f2543Smrg } 1079706f2543Smrg return DRIDestroyContextPriv(pDRIContextPriv); 1080706f2543Smrg} 1081706f2543Smrg 1082706f2543Smrg 1083706f2543Smrg/* This walks the drawable timestamp array and invalidates all of them 1084706f2543Smrg * in the case of transition from private to shared backbuffers. It's 1085706f2543Smrg * not necessary for correctness, because DRIClipNotify gets called in 1086706f2543Smrg * time to prevent any conflict, but the transition from 1087706f2543Smrg * shared->private is sometimes missed if we don't do this. 1088706f2543Smrg */ 1089706f2543Smrgstatic void 1090706f2543SmrgDRIClipNotifyAllDrawables(ScreenPtr pScreen) 1091706f2543Smrg{ 1092706f2543Smrg int i; 1093706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1094706f2543Smrg 1095706f2543Smrg for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { 1096706f2543Smrg pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; 1097706f2543Smrg } 1098706f2543Smrg} 1099706f2543Smrg 1100706f2543Smrg 1101706f2543Smrgstatic void 1102706f2543SmrgDRITransitionToSharedBuffers(ScreenPtr pScreen) 1103706f2543Smrg{ 1104706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1105706f2543Smrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1106706f2543Smrg 1107706f2543Smrg DRIClipNotifyAllDrawables( pScreen ); 1108706f2543Smrg 1109706f2543Smrg if (pDRIInfo->TransitionSingleToMulti3D) 1110706f2543Smrg pDRIInfo->TransitionSingleToMulti3D( pScreen ); 1111706f2543Smrg} 1112706f2543Smrg 1113706f2543Smrg 1114706f2543Smrgstatic void 1115706f2543SmrgDRITransitionToPrivateBuffers(ScreenPtr pScreen) 1116706f2543Smrg{ 1117706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1118706f2543Smrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1119706f2543Smrg 1120706f2543Smrg DRIClipNotifyAllDrawables( pScreen ); 1121706f2543Smrg 1122706f2543Smrg if (pDRIInfo->TransitionMultiToSingle3D) 1123706f2543Smrg pDRIInfo->TransitionMultiToSingle3D( pScreen ); 1124706f2543Smrg} 1125706f2543Smrg 1126706f2543Smrg 1127706f2543Smrgstatic void 1128706f2543SmrgDRITransitionTo3d(ScreenPtr pScreen) 1129706f2543Smrg{ 1130706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1131706f2543Smrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1132706f2543Smrg 1133706f2543Smrg DRIClipNotifyAllDrawables( pScreen ); 1134706f2543Smrg 1135706f2543Smrg if (pDRIInfo->TransitionTo3d) 1136706f2543Smrg pDRIInfo->TransitionTo3d( pScreen ); 1137706f2543Smrg} 1138706f2543Smrg 1139706f2543Smrgstatic void 1140706f2543SmrgDRITransitionTo2d(ScreenPtr pScreen) 1141706f2543Smrg{ 1142706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1143706f2543Smrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1144706f2543Smrg 1145706f2543Smrg DRIClipNotifyAllDrawables( pScreen ); 1146706f2543Smrg 1147706f2543Smrg if (pDRIInfo->TransitionTo2d) 1148706f2543Smrg pDRIInfo->TransitionTo2d( pScreen ); 1149706f2543Smrg} 1150706f2543Smrg 1151706f2543Smrg 1152706f2543Smrgstatic int 1153706f2543SmrgDRIDCNTreeTraversal(WindowPtr pWin, pointer data) 1154706f2543Smrg{ 1155706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1156706f2543Smrg 1157706f2543Smrg if (pDRIDrawablePriv) { 1158706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1159706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1160706f2543Smrg 1161706f2543Smrg if (RegionNumRects(&pWin->clipList) > 0) { 1162706f2543Smrg WindowPtr *pDRIWindows = (WindowPtr*)data; 1163706f2543Smrg int i = 0; 1164706f2543Smrg 1165706f2543Smrg while (pDRIWindows[i]) 1166706f2543Smrg i++; 1167706f2543Smrg 1168706f2543Smrg pDRIWindows[i] = pWin; 1169706f2543Smrg 1170706f2543Smrg pDRIPriv->nrWalked++; 1171706f2543Smrg } 1172706f2543Smrg 1173706f2543Smrg if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) 1174706f2543Smrg return WT_STOPWALKING; 1175706f2543Smrg } 1176706f2543Smrg 1177706f2543Smrg return WT_WALKCHILDREN; 1178706f2543Smrg} 1179706f2543Smrg 1180706f2543Smrgstatic void 1181706f2543SmrgDRIDriverClipNotify(ScreenPtr pScreen) 1182706f2543Smrg{ 1183706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1184706f2543Smrg 1185706f2543Smrg if (pDRIPriv->pDriverInfo->ClipNotify) { 1186706f2543Smrg WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows); 1187706f2543Smrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1188706f2543Smrg 1189706f2543Smrg if (pDRIPriv->nrWindows > 0) { 1190706f2543Smrg pDRIPriv->nrWalked = 0; 1191706f2543Smrg TraverseTree(pScreen->root, DRIDCNTreeTraversal, 1192706f2543Smrg (pointer)pDRIWindows); 1193706f2543Smrg } 1194706f2543Smrg 1195706f2543Smrg pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows); 1196706f2543Smrg 1197706f2543Smrg free(pDRIWindows); 1198706f2543Smrg } 1199706f2543Smrg} 1200706f2543Smrg 1201706f2543Smrgstatic void 1202706f2543SmrgDRIIncreaseNumberVisible(ScreenPtr pScreen) 1203706f2543Smrg{ 1204706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1205706f2543Smrg 1206706f2543Smrg switch (++pDRIPriv->nrWindowsVisible) { 1207706f2543Smrg case 1: 1208706f2543Smrg DRITransitionTo3d( pScreen ); 1209706f2543Smrg break; 1210706f2543Smrg case 2: 1211706f2543Smrg DRITransitionToSharedBuffers( pScreen ); 1212706f2543Smrg break; 1213706f2543Smrg default: 1214706f2543Smrg break; 1215706f2543Smrg } 1216706f2543Smrg 1217706f2543Smrg DRIDriverClipNotify(pScreen); 1218706f2543Smrg} 1219706f2543Smrg 1220706f2543Smrgstatic void 1221706f2543SmrgDRIDecreaseNumberVisible(ScreenPtr pScreen) 1222706f2543Smrg{ 1223706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1224706f2543Smrg 1225706f2543Smrg switch (--pDRIPriv->nrWindowsVisible) { 1226706f2543Smrg case 0: 1227706f2543Smrg DRITransitionTo2d( pScreen ); 1228706f2543Smrg break; 1229706f2543Smrg case 1: 1230706f2543Smrg DRITransitionToPrivateBuffers( pScreen ); 1231706f2543Smrg break; 1232706f2543Smrg default: 1233706f2543Smrg break; 1234706f2543Smrg } 1235706f2543Smrg 1236706f2543Smrg DRIDriverClipNotify(pScreen); 1237706f2543Smrg} 1238706f2543Smrg 1239706f2543SmrgBool 1240706f2543SmrgDRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable, 1241706f2543Smrg drm_drawable_t * hHWDrawable) 1242706f2543Smrg{ 1243706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1244706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 1245706f2543Smrg WindowPtr pWin; 1246706f2543Smrg 1247706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 1248706f2543Smrg pWin = (WindowPtr)pDrawable; 1249706f2543Smrg if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 1250706f2543Smrg pDRIDrawablePriv->refCount++; 1251706f2543Smrg 1252706f2543Smrg if (!pDRIDrawablePriv->hwDrawable) { 1253706f2543Smrg drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable); 1254706f2543Smrg } 1255706f2543Smrg } 1256706f2543Smrg else { 1257706f2543Smrg /* allocate a DRI Window Private record */ 1258706f2543Smrg if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) { 1259706f2543Smrg return FALSE; 1260706f2543Smrg } 1261706f2543Smrg 1262706f2543Smrg /* Only create a drm_drawable_t once */ 1263706f2543Smrg if (drmCreateDrawable(pDRIPriv->drmFD, 1264706f2543Smrg &pDRIDrawablePriv->hwDrawable)) { 1265706f2543Smrg free(pDRIDrawablePriv); 1266706f2543Smrg return FALSE; 1267706f2543Smrg } 1268706f2543Smrg 1269706f2543Smrg /* add it to the list of DRI drawables for this screen */ 1270706f2543Smrg pDRIDrawablePriv->pScreen = pScreen; 1271706f2543Smrg pDRIDrawablePriv->refCount = 1; 1272706f2543Smrg pDRIDrawablePriv->drawableIndex = -1; 1273706f2543Smrg pDRIDrawablePriv->nrects = RegionNumRects(&pWin->clipList); 1274706f2543Smrg 1275706f2543Smrg /* save private off of preallocated index */ 1276706f2543Smrg dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, 1277706f2543Smrg pDRIDrawablePriv); 1278706f2543Smrg pDRIPriv->nrWindows++; 1279706f2543Smrg 1280706f2543Smrg if (pDRIDrawablePriv->nrects) 1281706f2543Smrg DRIIncreaseNumberVisible(pScreen); 1282706f2543Smrg } 1283706f2543Smrg 1284706f2543Smrg /* track this in case the client dies */ 1285706f2543Smrg AddResource(FakeClientID(client->index), DRIDrawablePrivResType, 1286706f2543Smrg (pointer)(intptr_t)pDrawable->id); 1287706f2543Smrg 1288706f2543Smrg if (pDRIDrawablePriv->hwDrawable) { 1289706f2543Smrg drmUpdateDrawableInfo(pDRIPriv->drmFD, 1290706f2543Smrg pDRIDrawablePriv->hwDrawable, 1291706f2543Smrg DRM_DRAWABLE_CLIPRECTS, 1292706f2543Smrg RegionNumRects(&pWin->clipList), 1293706f2543Smrg RegionRects(&pWin->clipList)); 1294706f2543Smrg *hHWDrawable = pDRIDrawablePriv->hwDrawable; 1295706f2543Smrg } 1296706f2543Smrg } 1297706f2543Smrg else if (pDrawable->type != DRAWABLE_PIXMAP) { /* PBuffer */ 1298706f2543Smrg /* NOT_DONE */ 1299706f2543Smrg return FALSE; 1300706f2543Smrg } 1301706f2543Smrg 1302706f2543Smrg return TRUE; 1303706f2543Smrg} 1304706f2543Smrg 1305706f2543Smrgstatic void 1306706f2543SmrgDRIDrawablePrivDestroy(WindowPtr pWin) 1307706f2543Smrg{ 1308706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1309706f2543Smrg ScreenPtr pScreen; 1310706f2543Smrg DRIScreenPrivPtr pDRIPriv; 1311706f2543Smrg 1312706f2543Smrg if (!pDRIDrawablePriv) 1313706f2543Smrg return; 1314706f2543Smrg 1315706f2543Smrg pScreen = pWin->drawable.pScreen; 1316706f2543Smrg pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1317706f2543Smrg 1318706f2543Smrg if (pDRIDrawablePriv->drawableIndex != -1) { 1319706f2543Smrg /* bump stamp to force outstanding 3D requests to resync */ 1320706f2543Smrg pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp 1321706f2543Smrg = DRIDrawableValidationStamp++; 1322706f2543Smrg 1323706f2543Smrg /* release drawable table entry */ 1324706f2543Smrg pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; 1325706f2543Smrg } 1326706f2543Smrg 1327706f2543Smrg pDRIPriv->nrWindows--; 1328706f2543Smrg 1329706f2543Smrg if (pDRIDrawablePriv->nrects) 1330706f2543Smrg DRIDecreaseNumberVisible(pScreen); 1331706f2543Smrg 1332706f2543Smrg drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable); 1333706f2543Smrg 1334706f2543Smrg free(pDRIDrawablePriv); 1335706f2543Smrg dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); 1336706f2543Smrg} 1337706f2543Smrg 1338706f2543Smrgstatic Bool 1339706f2543SmrgDRIDestroyDrawableCB(pointer value, XID id, pointer data) 1340706f2543Smrg{ 1341706f2543Smrg if (value == data) { 1342706f2543Smrg /* This calls back DRIDrawablePrivDelete which frees private area */ 1343706f2543Smrg FreeResourceByType(id, DRIDrawablePrivResType, FALSE); 1344706f2543Smrg 1345706f2543Smrg return TRUE; 1346706f2543Smrg } 1347706f2543Smrg 1348706f2543Smrg return FALSE; 1349706f2543Smrg} 1350706f2543Smrg 1351706f2543SmrgBool 1352706f2543SmrgDRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable) 1353706f2543Smrg{ 1354706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 1355706f2543Smrg LookupClientResourceComplex(client, DRIDrawablePrivResType, 1356706f2543Smrg DRIDestroyDrawableCB, 1357706f2543Smrg (pointer)(intptr_t)pDrawable->id); 1358706f2543Smrg } 1359706f2543Smrg else { /* pixmap (or for GLX 1.3, a PBuffer) */ 1360706f2543Smrg /* NOT_DONE */ 1361706f2543Smrg return FALSE; 1362706f2543Smrg } 1363706f2543Smrg 1364706f2543Smrg return TRUE; 1365706f2543Smrg} 1366706f2543Smrg 1367706f2543SmrgBool 1368706f2543SmrgDRIDrawablePrivDelete(pointer pResource, XID id) 1369706f2543Smrg{ 1370706f2543Smrg WindowPtr pWin; 1371706f2543Smrg int rc; 1372706f2543Smrg 1373706f2543Smrg /* For DRIDrawablePrivResType, the XID is the client's fake ID. The 1374706f2543Smrg * important XID is the value in pResource. */ 1375706f2543Smrg id = (XID)(intptr_t)pResource; 1376706f2543Smrg rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess); 1377706f2543Smrg 1378706f2543Smrg if (rc == Success) { 1379706f2543Smrg DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1380706f2543Smrg 1381706f2543Smrg if (!pDRIDrwPriv) 1382706f2543Smrg return FALSE; 1383706f2543Smrg 1384706f2543Smrg if (--pDRIDrwPriv->refCount == 0) 1385706f2543Smrg DRIDrawablePrivDestroy(pWin); 1386706f2543Smrg 1387706f2543Smrg return TRUE; 1388706f2543Smrg } 1389706f2543Smrg else { /* pixmap (or for GLX 1.3, a PBuffer) */ 1390706f2543Smrg /* NOT_DONE */ 1391706f2543Smrg return FALSE; 1392706f2543Smrg } 1393706f2543Smrg} 1394706f2543Smrg 1395706f2543SmrgBool 1396706f2543SmrgDRIGetDrawableInfo(ScreenPtr pScreen, 1397706f2543Smrg DrawablePtr pDrawable, 1398706f2543Smrg unsigned int* index, 1399706f2543Smrg unsigned int* stamp, 1400706f2543Smrg int* X, 1401706f2543Smrg int* Y, 1402706f2543Smrg int* W, 1403706f2543Smrg int* H, 1404706f2543Smrg int* numClipRects, 1405706f2543Smrg drm_clip_rect_t ** pClipRects, 1406706f2543Smrg int* backX, 1407706f2543Smrg int* backY, 1408706f2543Smrg int* numBackClipRects, 1409706f2543Smrg drm_clip_rect_t ** pBackClipRects) 1410706f2543Smrg{ 1411706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1412706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; 1413706f2543Smrg WindowPtr pWin, pOldWin; 1414706f2543Smrg int i; 1415706f2543Smrg 1416706f2543Smrg#if 0 1417706f2543Smrg printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry); 1418706f2543Smrg#endif 1419706f2543Smrg 1420706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 1421706f2543Smrg pWin = (WindowPtr)pDrawable; 1422706f2543Smrg if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 1423706f2543Smrg 1424706f2543Smrg /* Manage drawable table */ 1425706f2543Smrg if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ 1426706f2543Smrg 1427706f2543Smrg /* Search table for empty entry */ 1428706f2543Smrg i = 0; 1429706f2543Smrg while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { 1430706f2543Smrg if (!(pDRIPriv->DRIDrawables[i])) { 1431706f2543Smrg pDRIPriv->DRIDrawables[i] = pDrawable; 1432706f2543Smrg pDRIDrawablePriv->drawableIndex = i; 1433706f2543Smrg pDRIPriv->pSAREA->drawableTable[i].stamp = 1434706f2543Smrg DRIDrawableValidationStamp++; 1435706f2543Smrg break; 1436706f2543Smrg } 1437706f2543Smrg i++; 1438706f2543Smrg } 1439706f2543Smrg 1440706f2543Smrg /* Search table for oldest entry */ 1441706f2543Smrg if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { 1442706f2543Smrg unsigned int oldestStamp = ~0; 1443706f2543Smrg int oldestIndex = 0; 1444706f2543Smrg i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; 1445706f2543Smrg while (i--) { 1446706f2543Smrg if (pDRIPriv->pSAREA->drawableTable[i].stamp < 1447706f2543Smrg oldestStamp) { 1448706f2543Smrg oldestIndex = i; 1449706f2543Smrg oldestStamp = 1450706f2543Smrg pDRIPriv->pSAREA->drawableTable[i].stamp; 1451706f2543Smrg } 1452706f2543Smrg } 1453706f2543Smrg pDRIDrawablePriv->drawableIndex = oldestIndex; 1454706f2543Smrg 1455706f2543Smrg /* release oldest drawable table entry */ 1456706f2543Smrg pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex]; 1457706f2543Smrg pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); 1458706f2543Smrg pOldDrawPriv->drawableIndex = -1; 1459706f2543Smrg 1460706f2543Smrg /* claim drawable table entry */ 1461706f2543Smrg pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; 1462706f2543Smrg 1463706f2543Smrg /* validate SAREA entry */ 1464706f2543Smrg pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = 1465706f2543Smrg DRIDrawableValidationStamp++; 1466706f2543Smrg 1467706f2543Smrg /* check for stamp wrap around */ 1468706f2543Smrg if (oldestStamp > DRIDrawableValidationStamp) { 1469706f2543Smrg 1470706f2543Smrg /* walk SAREA table and invalidate all drawables */ 1471706f2543Smrg for( i=0; 1472706f2543Smrg i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; 1473706f2543Smrg i++) { 1474706f2543Smrg pDRIPriv->pSAREA->drawableTable[i].stamp = 1475706f2543Smrg DRIDrawableValidationStamp++; 1476706f2543Smrg } 1477706f2543Smrg } 1478706f2543Smrg } 1479706f2543Smrg 1480706f2543Smrg /* If the driver wants to be notified when the index is 1481706f2543Smrg * set for a drawable, let it know now. 1482706f2543Smrg */ 1483706f2543Smrg if (pDRIPriv->pDriverInfo->SetDrawableIndex) 1484706f2543Smrg pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, 1485706f2543Smrg pDRIDrawablePriv->drawableIndex); 1486706f2543Smrg 1487706f2543Smrg /* reinit drawable ID if window is visible */ 1488706f2543Smrg if ((pWin->viewable) && 1489706f2543Smrg (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) 1490706f2543Smrg { 1491706f2543Smrg (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, 1492706f2543Smrg &pWin->clipList, pDRIDrawablePriv->drawableIndex); 1493706f2543Smrg } 1494706f2543Smrg } 1495706f2543Smrg 1496706f2543Smrg *index = pDRIDrawablePriv->drawableIndex; 1497706f2543Smrg *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; 1498706f2543Smrg *X = (int)(pWin->drawable.x); 1499706f2543Smrg *Y = (int)(pWin->drawable.y); 1500706f2543Smrg#if 0 1501706f2543Smrg *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1); 1502706f2543Smrg *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1); 1503706f2543Smrg#endif 1504706f2543Smrg *W = (int)(pWin->drawable.width); 1505706f2543Smrg *H = (int)(pWin->drawable.height); 1506706f2543Smrg *numClipRects = RegionNumRects(&pWin->clipList); 1507706f2543Smrg *pClipRects = (drm_clip_rect_t *)RegionRects(&pWin->clipList); 1508706f2543Smrg 1509706f2543Smrg if (!*numClipRects && pDRIPriv->fullscreen) { 1510706f2543Smrg /* use fake full-screen clip rect */ 1511706f2543Smrg pDRIPriv->fullscreen_rect.x1 = *X; 1512706f2543Smrg pDRIPriv->fullscreen_rect.y1 = *Y; 1513706f2543Smrg pDRIPriv->fullscreen_rect.x2 = *X + *W; 1514706f2543Smrg pDRIPriv->fullscreen_rect.y2 = *Y + *H; 1515706f2543Smrg 1516706f2543Smrg *numClipRects = 1; 1517706f2543Smrg *pClipRects = &pDRIPriv->fullscreen_rect; 1518706f2543Smrg } 1519706f2543Smrg 1520706f2543Smrg *backX = *X; 1521706f2543Smrg *backY = *Y; 1522706f2543Smrg 1523706f2543Smrg if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) { 1524706f2543Smrg /* Use a single cliprect. */ 1525706f2543Smrg 1526706f2543Smrg int x0 = *X; 1527706f2543Smrg int y0 = *Y; 1528706f2543Smrg int x1 = x0 + *W; 1529706f2543Smrg int y1 = y0 + *H; 1530706f2543Smrg 1531706f2543Smrg if (x0 < 0) x0 = 0; 1532706f2543Smrg if (y0 < 0) y0 = 0; 1533706f2543Smrg if (x1 > pScreen->width) x1 = pScreen->width; 1534706f2543Smrg if (y1 > pScreen->height) y1 = pScreen->height; 1535706f2543Smrg 1536706f2543Smrg if (y0 >= y1 || x0 >= x1) { 1537706f2543Smrg *numBackClipRects = 0; 1538706f2543Smrg *pBackClipRects = NULL; 1539706f2543Smrg } else { 1540706f2543Smrg pDRIPriv->private_buffer_rect.x1 = x0; 1541706f2543Smrg pDRIPriv->private_buffer_rect.y1 = y0; 1542706f2543Smrg pDRIPriv->private_buffer_rect.x2 = x1; 1543706f2543Smrg pDRIPriv->private_buffer_rect.y2 = y1; 1544706f2543Smrg 1545706f2543Smrg *numBackClipRects = 1; 1546706f2543Smrg *pBackClipRects = &(pDRIPriv->private_buffer_rect); 1547706f2543Smrg } 1548706f2543Smrg } else { 1549706f2543Smrg /* Use the frontbuffer cliprects for back buffers. */ 1550706f2543Smrg *numBackClipRects = 0; 1551706f2543Smrg *pBackClipRects = 0; 1552706f2543Smrg } 1553706f2543Smrg } 1554706f2543Smrg else { 1555706f2543Smrg /* Not a DRIDrawable */ 1556706f2543Smrg return FALSE; 1557706f2543Smrg } 1558706f2543Smrg } 1559706f2543Smrg else { /* pixmap (or for GLX 1.3, a PBuffer) */ 1560706f2543Smrg /* NOT_DONE */ 1561706f2543Smrg return FALSE; 1562706f2543Smrg } 1563706f2543Smrg 1564706f2543Smrg return TRUE; 1565706f2543Smrg} 1566706f2543Smrg 1567706f2543SmrgBool 1568706f2543SmrgDRIGetDeviceInfo(ScreenPtr pScreen, 1569706f2543Smrg drm_handle_t * hFrameBuffer, 1570706f2543Smrg int* fbOrigin, 1571706f2543Smrg int* fbSize, 1572706f2543Smrg int* fbStride, 1573706f2543Smrg int* devPrivateSize, 1574706f2543Smrg void** pDevPrivate) 1575706f2543Smrg{ 1576706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1577706f2543Smrg 1578706f2543Smrg *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer; 1579706f2543Smrg *fbOrigin = 0; 1580706f2543Smrg *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; 1581706f2543Smrg *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; 1582706f2543Smrg *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; 1583706f2543Smrg *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; 1584706f2543Smrg 1585706f2543Smrg return TRUE; 1586706f2543Smrg} 1587706f2543Smrg 1588706f2543SmrgDRIInfoPtr 1589706f2543SmrgDRICreateInfoRec(void) 1590706f2543Smrg{ 1591706f2543Smrg DRIInfoPtr inforec = (DRIInfoPtr)calloc(1, sizeof(DRIInfoRec)); 1592706f2543Smrg if (!inforec) return NULL; 1593706f2543Smrg 1594706f2543Smrg /* Initialize defaults */ 1595706f2543Smrg inforec->busIdString = NULL; 1596706f2543Smrg 1597706f2543Smrg /* Wrapped function defaults */ 1598706f2543Smrg inforec->wrap.WakeupHandler = DRIDoWakeupHandler; 1599706f2543Smrg inforec->wrap.BlockHandler = DRIDoBlockHandler; 1600706f2543Smrg inforec->wrap.WindowExposures = DRIWindowExposures; 1601706f2543Smrg inforec->wrap.CopyWindow = DRICopyWindow; 1602706f2543Smrg inforec->wrap.ValidateTree = DRIValidateTree; 1603706f2543Smrg inforec->wrap.PostValidateTree = DRIPostValidateTree; 1604706f2543Smrg inforec->wrap.ClipNotify = DRIClipNotify; 1605706f2543Smrg inforec->wrap.AdjustFrame = DRIAdjustFrame; 1606706f2543Smrg 1607706f2543Smrg inforec->TransitionTo2d = 0; 1608706f2543Smrg inforec->TransitionTo3d = 0; 1609706f2543Smrg inforec->SetDrawableIndex = 0; 1610706f2543Smrg 1611706f2543Smrg return inforec; 1612706f2543Smrg} 1613706f2543Smrg 1614706f2543Smrgvoid 1615706f2543SmrgDRIDestroyInfoRec(DRIInfoPtr DRIInfo) 1616706f2543Smrg{ 1617706f2543Smrg free(DRIInfo->busIdString); 1618706f2543Smrg free((char*)DRIInfo); 1619706f2543Smrg} 1620706f2543Smrg 1621706f2543Smrg 1622706f2543Smrgvoid 1623706f2543SmrgDRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask) 1624706f2543Smrg{ 1625706f2543Smrg int i; 1626706f2543Smrg 1627706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1628706f2543Smrg ScreenPtr pScreen = screenInfo.screens[i]; 1629706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1630706f2543Smrg 1631706f2543Smrg if (pDRIPriv && 1632706f2543Smrg pDRIPriv->pDriverInfo->wrap.WakeupHandler) 1633706f2543Smrg (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData, 1634706f2543Smrg result, pReadmask); 1635706f2543Smrg } 1636706f2543Smrg} 1637706f2543Smrg 1638706f2543Smrgvoid 1639706f2543SmrgDRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) 1640706f2543Smrg{ 1641706f2543Smrg int i; 1642706f2543Smrg 1643706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1644706f2543Smrg ScreenPtr pScreen = screenInfo.screens[i]; 1645706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1646706f2543Smrg 1647706f2543Smrg if (pDRIPriv && 1648706f2543Smrg pDRIPriv->pDriverInfo->wrap.BlockHandler) 1649706f2543Smrg (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData, 1650706f2543Smrg pTimeout, pReadmask); 1651706f2543Smrg } 1652706f2543Smrg} 1653706f2543Smrg 1654706f2543Smrgvoid 1655706f2543SmrgDRIDoWakeupHandler(int screenNum, pointer wakeupData, 1656706f2543Smrg unsigned long result, pointer pReadmask) 1657706f2543Smrg{ 1658706f2543Smrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 1659706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1660706f2543Smrg 1661706f2543Smrg DRILock(pScreen, 0); 1662706f2543Smrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 1663706f2543Smrg /* hide X context by swapping 2D component here */ 1664706f2543Smrg (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1665706f2543Smrg DRI_3D_SYNC, 1666706f2543Smrg DRI_2D_CONTEXT, 1667706f2543Smrg pDRIPriv->partial3DContextStore, 1668706f2543Smrg DRI_2D_CONTEXT, 1669706f2543Smrg pDRIPriv->hiddenContextStore); 1670706f2543Smrg } 1671706f2543Smrg} 1672706f2543Smrg 1673706f2543Smrgvoid 1674706f2543SmrgDRIDoBlockHandler(int screenNum, pointer blockData, 1675706f2543Smrg pointer pTimeout, pointer pReadmask) 1676706f2543Smrg{ 1677706f2543Smrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 1678706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1679706f2543Smrg 1680706f2543Smrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 1681706f2543Smrg /* hide X context by swapping 2D component here */ 1682706f2543Smrg (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1683706f2543Smrg DRI_2D_SYNC, 1684706f2543Smrg DRI_NO_CONTEXT, 1685706f2543Smrg NULL, 1686706f2543Smrg DRI_2D_CONTEXT, 1687706f2543Smrg pDRIPriv->partial3DContextStore); 1688706f2543Smrg } 1689706f2543Smrg 1690706f2543Smrg if (pDRIPriv->windowsTouched) 1691706f2543Smrg DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); 1692706f2543Smrg pDRIPriv->windowsTouched = FALSE; 1693706f2543Smrg 1694706f2543Smrg DRIUnlock(pScreen); 1695706f2543Smrg} 1696706f2543Smrg 1697706f2543Smrgvoid 1698706f2543SmrgDRISwapContext(int drmFD, void *oldctx, void *newctx) 1699706f2543Smrg{ 1700706f2543Smrg DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx; 1701706f2543Smrg DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx; 1702706f2543Smrg ScreenPtr pScreen = newContext->pScreen; 1703706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1704706f2543Smrg void* oldContextStore = NULL; 1705706f2543Smrg DRIContextType oldContextType; 1706706f2543Smrg void* newContextStore = NULL; 1707706f2543Smrg DRIContextType newContextType; 1708706f2543Smrg DRISyncType syncType; 1709706f2543Smrg#ifdef DEBUG 1710706f2543Smrg static int count = 0; 1711706f2543Smrg 1712706f2543Smrg if (!newContext) { 1713706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 1714706f2543Smrg "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n", 1715706f2543Smrg oldContext, newContext); 1716706f2543Smrg return; 1717706f2543Smrg } 1718706f2543Smrg 1719706f2543Smrg /* usefull for debugging, just print out after n context switches */ 1720706f2543Smrg if (!count || !(count % 1)) { 1721706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 1722706f2543Smrg "[DRI] Context switch %5d from %p/0x%08x (%d)\n", 1723706f2543Smrg count, 1724706f2543Smrg oldContext, 1725706f2543Smrg oldContext ? oldContext->flags : 0, 1726706f2543Smrg oldContext ? oldContext->hwContext : -1); 1727706f2543Smrg DRIDrvMsg(pScreen->myNum, X_INFO, 1728706f2543Smrg "[DRI] Context switch %5d to %p/0x%08x (%d)\n", 1729706f2543Smrg count, 1730706f2543Smrg newContext, 1731706f2543Smrg newContext ? newContext->flags : 0, 1732706f2543Smrg newContext ? newContext->hwContext : -1); 1733706f2543Smrg } 1734706f2543Smrg ++count; 1735706f2543Smrg#endif 1736706f2543Smrg 1737706f2543Smrg if (!pDRIPriv->pDriverInfo->SwapContext) { 1738706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 1739706f2543Smrg "[DRI] DDX driver missing context swap call back\n"); 1740706f2543Smrg return; 1741706f2543Smrg } 1742706f2543Smrg 1743706f2543Smrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 1744706f2543Smrg 1745706f2543Smrg /* only 3D contexts are swapped in this case */ 1746706f2543Smrg if (oldContext) { 1747706f2543Smrg oldContextStore = DRIGetContextStore(oldContext); 1748706f2543Smrg oldContext->valid3D = TRUE; 1749706f2543Smrg oldContextType = DRI_3D_CONTEXT; 1750706f2543Smrg } else { 1751706f2543Smrg oldContextType = DRI_NO_CONTEXT; 1752706f2543Smrg } 1753706f2543Smrg newContextStore = DRIGetContextStore(newContext); 1754706f2543Smrg if ((newContext->valid3D) && 1755706f2543Smrg (newContext->hwContext != pDRIPriv->myContext)) { 1756706f2543Smrg newContextType = DRI_3D_CONTEXT; 1757706f2543Smrg } 1758706f2543Smrg else { 1759706f2543Smrg newContextType = DRI_2D_CONTEXT; 1760706f2543Smrg } 1761706f2543Smrg syncType = DRI_3D_SYNC; 1762706f2543Smrg } 1763706f2543Smrg else /* default: driverSwapMethod == DRI_SERVER_SWAP */ { 1764706f2543Smrg 1765706f2543Smrg /* optimize 2D context swaps */ 1766706f2543Smrg 1767706f2543Smrg if (newContext->flags & DRI_CONTEXT_2DONLY) { 1768706f2543Smrg /* go from 3D context to 2D context and only save 2D 1769706f2543Smrg * subset of 3D state 1770706f2543Smrg */ 1771706f2543Smrg oldContextStore = DRIGetContextStore(oldContext); 1772706f2543Smrg oldContextType = DRI_2D_CONTEXT; 1773706f2543Smrg newContextStore = DRIGetContextStore(newContext); 1774706f2543Smrg newContextType = DRI_2D_CONTEXT; 1775706f2543Smrg syncType = DRI_3D_SYNC; 1776706f2543Smrg pDRIPriv->lastPartial3DContext = oldContext; 1777706f2543Smrg } 1778706f2543Smrg else if (oldContext->flags & DRI_CONTEXT_2DONLY) { 1779706f2543Smrg if (pDRIPriv->lastPartial3DContext == newContext) { 1780706f2543Smrg /* go from 2D context back to previous 3D context and 1781706f2543Smrg * only restore 2D subset of previous 3D state 1782706f2543Smrg */ 1783706f2543Smrg oldContextStore = DRIGetContextStore(oldContext); 1784706f2543Smrg oldContextType = DRI_2D_CONTEXT; 1785706f2543Smrg newContextStore = DRIGetContextStore(newContext); 1786706f2543Smrg newContextType = DRI_2D_CONTEXT; 1787706f2543Smrg syncType = DRI_2D_SYNC; 1788706f2543Smrg } 1789706f2543Smrg else { 1790706f2543Smrg /* go from 2D context to a different 3D context */ 1791706f2543Smrg 1792706f2543Smrg /* call DDX driver to do partial restore */ 1793706f2543Smrg oldContextStore = DRIGetContextStore(oldContext); 1794706f2543Smrg newContextStore = 1795706f2543Smrg DRIGetContextStore(pDRIPriv->lastPartial3DContext); 1796706f2543Smrg (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1797706f2543Smrg DRI_2D_SYNC, 1798706f2543Smrg DRI_2D_CONTEXT, 1799706f2543Smrg oldContextStore, 1800706f2543Smrg DRI_2D_CONTEXT, 1801706f2543Smrg newContextStore); 1802706f2543Smrg 1803706f2543Smrg /* now setup for a complete 3D swap */ 1804706f2543Smrg oldContextStore = newContextStore; 1805706f2543Smrg oldContext->valid3D = TRUE; 1806706f2543Smrg oldContextType = DRI_3D_CONTEXT; 1807706f2543Smrg newContextStore = DRIGetContextStore(newContext); 1808706f2543Smrg if ((newContext->valid3D) && 1809706f2543Smrg (newContext->hwContext != pDRIPriv->myContext)) { 1810706f2543Smrg newContextType = DRI_3D_CONTEXT; 1811706f2543Smrg } 1812706f2543Smrg else { 1813706f2543Smrg newContextType = DRI_2D_CONTEXT; 1814706f2543Smrg } 1815706f2543Smrg syncType = DRI_NO_SYNC; 1816706f2543Smrg } 1817706f2543Smrg } 1818706f2543Smrg else { 1819706f2543Smrg /* now setup for a complete 3D swap */ 1820706f2543Smrg oldContextStore = newContextStore; 1821706f2543Smrg oldContext->valid3D = TRUE; 1822706f2543Smrg oldContextType = DRI_3D_CONTEXT; 1823706f2543Smrg newContextStore = DRIGetContextStore(newContext); 1824706f2543Smrg if ((newContext->valid3D) && 1825706f2543Smrg (newContext->hwContext != pDRIPriv->myContext)) { 1826706f2543Smrg newContextType = DRI_3D_CONTEXT; 1827706f2543Smrg } 1828706f2543Smrg else { 1829706f2543Smrg newContextType = DRI_2D_CONTEXT; 1830706f2543Smrg } 1831706f2543Smrg syncType = DRI_3D_SYNC; 1832706f2543Smrg } 1833706f2543Smrg } 1834706f2543Smrg 1835706f2543Smrg /* call DDX driver to perform the swap */ 1836706f2543Smrg (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1837706f2543Smrg syncType, 1838706f2543Smrg oldContextType, 1839706f2543Smrg oldContextStore, 1840706f2543Smrg newContextType, 1841706f2543Smrg newContextStore); 1842706f2543Smrg} 1843706f2543Smrg 1844706f2543Smrgvoid* 1845706f2543SmrgDRIGetContextStore(DRIContextPrivPtr context) 1846706f2543Smrg{ 1847706f2543Smrg return((void *)context->pContextStore); 1848706f2543Smrg} 1849706f2543Smrg 1850706f2543Smrgvoid 1851706f2543SmrgDRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) 1852706f2543Smrg{ 1853706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1854706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1855706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1856706f2543Smrg 1857706f2543Smrg if(pDRIDrawablePriv) { 1858706f2543Smrg (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn, 1859706f2543Smrg pDRIDrawablePriv->drawableIndex); 1860706f2543Smrg } 1861706f2543Smrg 1862706f2543Smrg /* call lower wrapped functions */ 1863706f2543Smrg if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { 1864706f2543Smrg 1865706f2543Smrg /* unwrap */ 1866706f2543Smrg pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 1867706f2543Smrg 1868706f2543Smrg /* call lower layers */ 1869706f2543Smrg (*pScreen->WindowExposures)(pWin, prgn, bsreg); 1870706f2543Smrg 1871706f2543Smrg /* rewrap */ 1872706f2543Smrg pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 1873706f2543Smrg pScreen->WindowExposures = DRIWindowExposures; 1874706f2543Smrg } 1875706f2543Smrg} 1876706f2543Smrg 1877706f2543Smrg 1878706f2543Smrgstatic int 1879706f2543SmrgDRITreeTraversal(WindowPtr pWin, pointer data) 1880706f2543Smrg{ 1881706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1882706f2543Smrg 1883706f2543Smrg if(pDRIDrawablePriv) { 1884706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1885706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1886706f2543Smrg 1887706f2543Smrg if(RegionNumRects(&(pWin->clipList)) > 0) { 1888706f2543Smrg RegionPtr reg = (RegionPtr)data; 1889706f2543Smrg 1890706f2543Smrg RegionUnion(reg, reg, &(pWin->clipList)); 1891706f2543Smrg pDRIPriv->nrWalked++; 1892706f2543Smrg } 1893706f2543Smrg 1894706f2543Smrg if(pDRIPriv->nrWindows == pDRIPriv->nrWalked) 1895706f2543Smrg return WT_STOPWALKING; 1896706f2543Smrg } 1897706f2543Smrg return WT_WALKCHILDREN; 1898706f2543Smrg} 1899706f2543Smrg 1900706f2543SmrgBool 1901706f2543SmrgDRIDestroyWindow(WindowPtr pWin) 1902706f2543Smrg{ 1903706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1904706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1905706f2543Smrg Bool retval = TRUE; 1906706f2543Smrg 1907706f2543Smrg DRIDrawablePrivDestroy(pWin); 1908706f2543Smrg 1909706f2543Smrg /* call lower wrapped functions */ 1910706f2543Smrg if(pDRIPriv->DestroyWindow) { 1911706f2543Smrg /* unwrap */ 1912706f2543Smrg pScreen->DestroyWindow = pDRIPriv->DestroyWindow; 1913706f2543Smrg 1914706f2543Smrg /* call lower layers */ 1915706f2543Smrg retval = (*pScreen->DestroyWindow)(pWin); 1916706f2543Smrg 1917706f2543Smrg /* rewrap */ 1918706f2543Smrg pDRIPriv->DestroyWindow = pScreen->DestroyWindow; 1919706f2543Smrg pScreen->DestroyWindow = DRIDestroyWindow; 1920706f2543Smrg } 1921706f2543Smrg 1922706f2543Smrg return retval; 1923706f2543Smrg} 1924706f2543Smrg 1925706f2543Smrgvoid 1926706f2543SmrgDRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 1927706f2543Smrg{ 1928706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1929706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1930706f2543Smrg 1931706f2543Smrg if(!pDRIPriv) return; 1932706f2543Smrg 1933706f2543Smrg if(pDRIPriv->nrWindowsVisible > 0) { 1934706f2543Smrg RegionRec reg; 1935706f2543Smrg 1936706f2543Smrg RegionNull(®); 1937706f2543Smrg pDRIPriv->nrWalked = 0; 1938706f2543Smrg TraverseTree(pWin, DRITreeTraversal, (pointer)(®)); 1939706f2543Smrg 1940706f2543Smrg if(RegionNotEmpty(®)) { 1941706f2543Smrg RegionTranslate(®, ptOldOrg.x - pWin->drawable.x, 1942706f2543Smrg ptOldOrg.y - pWin->drawable.y); 1943706f2543Smrg RegionIntersect(®, ®, prgnSrc); 1944706f2543Smrg 1945706f2543Smrg /* The MoveBuffers interface is not ideal */ 1946706f2543Smrg (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®, 1947706f2543Smrg pDRIPriv->pDriverInfo->ddxDrawableTableEntry); 1948706f2543Smrg } 1949706f2543Smrg 1950706f2543Smrg RegionUninit(®); 1951706f2543Smrg } 1952706f2543Smrg 1953706f2543Smrg /* call lower wrapped functions */ 1954706f2543Smrg if(pDRIPriv->wrap.CopyWindow) { 1955706f2543Smrg /* unwrap */ 1956706f2543Smrg pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 1957706f2543Smrg 1958706f2543Smrg /* call lower layers */ 1959706f2543Smrg (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); 1960706f2543Smrg 1961706f2543Smrg /* rewrap */ 1962706f2543Smrg pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 1963706f2543Smrg pScreen->CopyWindow = DRICopyWindow; 1964706f2543Smrg } 1965706f2543Smrg} 1966706f2543Smrg 1967706f2543Smrgstatic void 1968706f2543SmrgDRIGetSecs(long *secs, long *usecs) 1969706f2543Smrg{ 1970706f2543Smrg struct timeval tv; 1971706f2543Smrg 1972706f2543Smrg gettimeofday(&tv, NULL); 1973706f2543Smrg 1974706f2543Smrg *secs = tv.tv_sec; 1975706f2543Smrg *usecs = tv.tv_usec; 1976706f2543Smrg} 1977706f2543Smrg 1978706f2543Smrgstatic unsigned long 1979706f2543SmrgDRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, 1980706f2543Smrg unsigned long f_secs, unsigned long f_usecs) 1981706f2543Smrg{ 1982706f2543Smrg if (f_usecs < s_usecs) { 1983706f2543Smrg --f_secs; 1984706f2543Smrg f_usecs += 1000000; 1985706f2543Smrg } 1986706f2543Smrg return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; 1987706f2543Smrg} 1988706f2543Smrg 1989706f2543Smrgstatic void 1990706f2543SmrgDRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */) 1991706f2543Smrg{ 1992706f2543Smrg int count = 10000; 1993706f2543Smrg#if !defined(__alpha__) && !defined(__powerpc__) 1994706f2543Smrg char ret; 1995706f2543Smrg#else 1996706f2543Smrg int ret; 1997706f2543Smrg#endif 1998706f2543Smrg long s_secs, s_usecs; 1999706f2543Smrg long f_secs, f_usecs; 2000706f2543Smrg long msecs; 2001706f2543Smrg long prev = 0; 2002706f2543Smrg 2003706f2543Smrg DRIGetSecs(&s_secs, &s_usecs); 2004706f2543Smrg 2005706f2543Smrg do { 2006706f2543Smrg DRM_SPINLOCK_COUNT(lock, val, count, ret); 2007706f2543Smrg if (!ret) return; /* Got lock */ 2008706f2543Smrg DRIGetSecs(&f_secs, &f_usecs); 2009706f2543Smrg msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); 2010706f2543Smrg if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */ 2011706f2543Smrg } while (msecs < timeout); 2012706f2543Smrg 2013706f2543Smrg /* Didn't get lock, so take it. The worst 2014706f2543Smrg that can happen is that there is some 2015706f2543Smrg garbage written to the wrong part of the 2016706f2543Smrg framebuffer that a refresh will repair. 2017706f2543Smrg That's undesirable, but better than 2018706f2543Smrg locking the server. This should be a 2019706f2543Smrg very rare event. */ 2020706f2543Smrg DRM_SPINLOCK_TAKE(lock, val); 2021706f2543Smrg} 2022706f2543Smrg 2023706f2543Smrgstatic void 2024706f2543SmrgDRILockTree(ScreenPtr pScreen) 2025706f2543Smrg{ 2026706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2027706f2543Smrg 2028706f2543Smrg if(!pDRIPriv) return; 2029706f2543Smrg 2030706f2543Smrg /* Restore the last known 3D context if the X context is hidden */ 2031706f2543Smrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 2032706f2543Smrg (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 2033706f2543Smrg DRI_2D_SYNC, 2034706f2543Smrg DRI_NO_CONTEXT, 2035706f2543Smrg NULL, 2036706f2543Smrg DRI_2D_CONTEXT, 2037706f2543Smrg pDRIPriv->partial3DContextStore); 2038706f2543Smrg } 2039706f2543Smrg 2040706f2543Smrg /* Call kernel to release lock */ 2041706f2543Smrg DRIUnlock(pScreen); 2042706f2543Smrg 2043706f2543Smrg /* Grab drawable spin lock: a time out between 10 and 30 seconds is 2044706f2543Smrg appropriate, since this should never time out except in the case of 2045706f2543Smrg client death while the lock is being held. The timeout must be 2046706f2543Smrg greater than any reasonable rendering time. */ 2047706f2543Smrg DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/ 2048706f2543Smrg 2049706f2543Smrg /* Call kernel flush outstanding buffers and relock */ 2050706f2543Smrg DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL); 2051706f2543Smrg 2052706f2543Smrg /* Switch back to our 2D context if the X context is hidden */ 2053706f2543Smrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 2054706f2543Smrg /* hide X context by swapping 2D component here */ 2055706f2543Smrg (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 2056706f2543Smrg DRI_3D_SYNC, 2057706f2543Smrg DRI_2D_CONTEXT, 2058706f2543Smrg pDRIPriv->partial3DContextStore, 2059706f2543Smrg DRI_2D_CONTEXT, 2060706f2543Smrg pDRIPriv->hiddenContextStore); 2061706f2543Smrg } 2062706f2543Smrg} 2063706f2543Smrg 2064706f2543Smrgint 2065706f2543SmrgDRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 2066706f2543Smrg{ 2067706f2543Smrg ScreenPtr pScreen = pParent->drawable.pScreen; 2068706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2069706f2543Smrg 2070706f2543Smrg int returnValue = 1; /* always return 1, not checked by dix/window.c */ 2071706f2543Smrg 2072706f2543Smrg if(!pDRIPriv) return returnValue; 2073706f2543Smrg 2074706f2543Smrg /* call lower wrapped functions */ 2075706f2543Smrg if(pDRIPriv->wrap.ValidateTree) { 2076706f2543Smrg /* unwrap */ 2077706f2543Smrg pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; 2078706f2543Smrg 2079706f2543Smrg /* call lower layers */ 2080706f2543Smrg returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); 2081706f2543Smrg 2082706f2543Smrg /* rewrap */ 2083706f2543Smrg pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 2084706f2543Smrg pScreen->ValidateTree = DRIValidateTree; 2085706f2543Smrg } 2086706f2543Smrg 2087706f2543Smrg return returnValue; 2088706f2543Smrg} 2089706f2543Smrg 2090706f2543Smrgvoid 2091706f2543SmrgDRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 2092706f2543Smrg{ 2093706f2543Smrg ScreenPtr pScreen; 2094706f2543Smrg DRIScreenPrivPtr pDRIPriv; 2095706f2543Smrg 2096706f2543Smrg if (pParent) { 2097706f2543Smrg pScreen = pParent->drawable.pScreen; 2098706f2543Smrg } else { 2099706f2543Smrg pScreen = pChild->drawable.pScreen; 2100706f2543Smrg } 2101706f2543Smrg if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return; 2102706f2543Smrg 2103706f2543Smrg if (pDRIPriv->wrap.PostValidateTree) { 2104706f2543Smrg /* unwrap */ 2105706f2543Smrg pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; 2106706f2543Smrg 2107706f2543Smrg /* call lower layers */ 2108706f2543Smrg (*pScreen->PostValidateTree)(pParent, pChild, kind); 2109706f2543Smrg 2110706f2543Smrg /* rewrap */ 2111706f2543Smrg pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 2112706f2543Smrg pScreen->PostValidateTree = DRIPostValidateTree; 2113706f2543Smrg } 2114706f2543Smrg} 2115706f2543Smrg 2116706f2543Smrgvoid 2117706f2543SmrgDRIClipNotify(WindowPtr pWin, int dx, int dy) 2118706f2543Smrg{ 2119706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 2120706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2121706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 2122706f2543Smrg 2123706f2543Smrg if(!pDRIPriv) return; 2124706f2543Smrg 2125706f2543Smrg if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 2126706f2543Smrg int nrects = RegionNumRects(&pWin->clipList); 2127706f2543Smrg 2128706f2543Smrg if(!pDRIPriv->windowsTouched) { 2129706f2543Smrg DRILockTree(pScreen); 2130706f2543Smrg pDRIPriv->windowsTouched = TRUE; 2131706f2543Smrg } 2132706f2543Smrg 2133706f2543Smrg if (nrects && !pDRIDrawablePriv->nrects) 2134706f2543Smrg DRIIncreaseNumberVisible(pScreen); 2135706f2543Smrg else if (!nrects && pDRIDrawablePriv->nrects) 2136706f2543Smrg DRIDecreaseNumberVisible(pScreen); 2137706f2543Smrg else 2138706f2543Smrg DRIDriverClipNotify(pScreen); 2139706f2543Smrg 2140706f2543Smrg pDRIDrawablePriv->nrects = nrects; 2141706f2543Smrg 2142706f2543Smrg pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp 2143706f2543Smrg = DRIDrawableValidationStamp++; 2144706f2543Smrg 2145706f2543Smrg drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable, 2146706f2543Smrg DRM_DRAWABLE_CLIPRECTS, 2147706f2543Smrg nrects, RegionRects(&pWin->clipList)); 2148706f2543Smrg } 2149706f2543Smrg 2150706f2543Smrg /* call lower wrapped functions */ 2151706f2543Smrg if(pDRIPriv->wrap.ClipNotify) { 2152706f2543Smrg 2153706f2543Smrg /* unwrap */ 2154706f2543Smrg pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 2155706f2543Smrg 2156706f2543Smrg /* call lower layers */ 2157706f2543Smrg (*pScreen->ClipNotify)(pWin, dx, dy); 2158706f2543Smrg 2159706f2543Smrg /* rewrap */ 2160706f2543Smrg pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 2161706f2543Smrg pScreen->ClipNotify = DRIClipNotify; 2162706f2543Smrg } 2163706f2543Smrg} 2164706f2543Smrg 2165706f2543SmrgCARD32 2166706f2543SmrgDRIGetDrawableIndex(WindowPtr pWin) 2167706f2543Smrg{ 2168706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 2169706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2170706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 2171706f2543Smrg CARD32 index; 2172706f2543Smrg 2173706f2543Smrg if (pDRIDrawablePriv) { 2174706f2543Smrg index = pDRIDrawablePriv->drawableIndex; 2175706f2543Smrg } 2176706f2543Smrg else { 2177706f2543Smrg index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; 2178706f2543Smrg } 2179706f2543Smrg 2180706f2543Smrg return index; 2181706f2543Smrg} 2182706f2543Smrg 2183706f2543Smrgunsigned int 2184706f2543SmrgDRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) 2185706f2543Smrg{ 2186706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2187706f2543Smrg return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; 2188706f2543Smrg} 2189706f2543Smrg 2190706f2543Smrg 2191706f2543Smrgvoid 2192706f2543SmrgDRIPrintDrawableLock(ScreenPtr pScreen, char *msg) 2193706f2543Smrg{ 2194706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2195706f2543Smrg 2196706f2543Smrg ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); 2197706f2543Smrg} 2198706f2543Smrg 2199706f2543Smrgvoid 2200706f2543SmrgDRILock(ScreenPtr pScreen, int flags) 2201706f2543Smrg{ 2202706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2203706f2543Smrg 2204706f2543Smrg if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; 2205706f2543Smrg 2206706f2543Smrg if (!*pDRIPriv->pLockRefCount) { 2207706f2543Smrg DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags); 2208706f2543Smrg *pDRIPriv->pLockingContext = pDRIPriv->myContext; 2209706f2543Smrg } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) { 2210706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 2211706f2543Smrg "[DRI] Locking deadlock.\n" 2212706f2543Smrg "\tAlready locked with context %d,\n" 2213706f2543Smrg "\ttrying to lock with context %d.\n", 2214706f2543Smrg pDRIPriv->pLockingContext, 2215706f2543Smrg pDRIPriv->myContext); 2216706f2543Smrg } 2217706f2543Smrg (*pDRIPriv->pLockRefCount)++; 2218706f2543Smrg} 2219706f2543Smrg 2220706f2543Smrgvoid 2221706f2543SmrgDRIUnlock(ScreenPtr pScreen) 2222706f2543Smrg{ 2223706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2224706f2543Smrg 2225706f2543Smrg if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; 2226706f2543Smrg 2227706f2543Smrg if (*pDRIPriv->pLockRefCount > 0) { 2228706f2543Smrg if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) { 2229706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 2230706f2543Smrg "[DRI] Unlocking inconsistency:\n" 2231706f2543Smrg "\tContext %d trying to unlock lock held by context %d\n", 2232706f2543Smrg pDRIPriv->pLockingContext, 2233706f2543Smrg pDRIPriv->myContext); 2234706f2543Smrg } 2235706f2543Smrg (*pDRIPriv->pLockRefCount)--; 2236706f2543Smrg } else { 2237706f2543Smrg DRIDrvMsg(pScreen->myNum, X_ERROR, 2238706f2543Smrg "DRIUnlock called when not locked.\n"); 2239706f2543Smrg return; 2240706f2543Smrg } 2241706f2543Smrg if (! *pDRIPriv->pLockRefCount) 2242706f2543Smrg DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext); 2243706f2543Smrg} 2244706f2543Smrg 2245706f2543Smrgvoid * 2246706f2543SmrgDRIGetSAREAPrivate(ScreenPtr pScreen) 2247706f2543Smrg{ 2248706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2249706f2543Smrg if (!pDRIPriv) return 0; 2250706f2543Smrg 2251706f2543Smrg return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec)); 2252706f2543Smrg} 2253706f2543Smrg 2254706f2543Smrgdrm_context_t 2255706f2543SmrgDRIGetContext(ScreenPtr pScreen) 2256706f2543Smrg{ 2257706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2258706f2543Smrg if (!pDRIPriv) return 0; 2259706f2543Smrg 2260706f2543Smrg return pDRIPriv->myContext; 2261706f2543Smrg} 2262706f2543Smrg 2263706f2543Smrgvoid 2264706f2543SmrgDRIGetTexOffsetFuncs(ScreenPtr pScreen, 2265706f2543Smrg DRITexOffsetStartProcPtr *texOffsetStartFunc, 2266706f2543Smrg DRITexOffsetFinishProcPtr *texOffsetFinishFunc) 2267706f2543Smrg{ 2268706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2269706f2543Smrg 2270706f2543Smrg if (!pDRIPriv) return; 2271706f2543Smrg 2272706f2543Smrg *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart; 2273706f2543Smrg *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish; 2274706f2543Smrg} 2275706f2543Smrg 2276706f2543Smrg/* This lets get at the unwrapped functions so that they can correctly 2277706f2543Smrg * call the lowerlevel functions, and choose whether they will be 2278706f2543Smrg * called at every level of recursion (eg in validatetree). 2279706f2543Smrg */ 2280706f2543SmrgDRIWrappedFuncsRec * 2281706f2543SmrgDRIGetWrappedFuncs(ScreenPtr pScreen) 2282706f2543Smrg{ 2283706f2543Smrg return &(DRI_SCREEN_PRIV(pScreen)->wrap); 2284706f2543Smrg} 2285706f2543Smrg 2286706f2543Smrg/* note that this returns the library version, not the protocol version */ 2287706f2543Smrgvoid 2288706f2543SmrgDRIQueryVersion(int *majorVersion, 2289706f2543Smrg int *minorVersion, 2290706f2543Smrg int *patchVersion) 2291706f2543Smrg{ 2292706f2543Smrg *majorVersion = DRIINFO_MAJOR_VERSION; 2293706f2543Smrg *minorVersion = DRIINFO_MINOR_VERSION; 2294706f2543Smrg *patchVersion = DRIINFO_PATCH_VERSION; 2295706f2543Smrg} 2296706f2543Smrg 2297706f2543Smrgstatic void 2298706f2543Smrg_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) 2299706f2543Smrg{ 2300706f2543Smrg pDRIPriv->pSAREA->frame.x = x; 2301706f2543Smrg pDRIPriv->pSAREA->frame.y = y; 2302706f2543Smrg pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; 2303706f2543Smrg pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; 2304706f2543Smrg} 2305706f2543Smrg 2306706f2543Smrgvoid 2307706f2543SmrgDRIAdjustFrame(int scrnIndex, int x, int y, int flags) 2308706f2543Smrg{ 2309706f2543Smrg ScreenPtr pScreen = screenInfo.screens[scrnIndex]; 2310706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2311706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2312706f2543Smrg int px, py; 2313706f2543Smrg 2314706f2543Smrg if (!pDRIPriv || !pDRIPriv->pSAREA) { 2315706f2543Smrg DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", 2316706f2543Smrg pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); 2317706f2543Smrg return; 2318706f2543Smrg } 2319706f2543Smrg 2320706f2543Smrg if (pDRIPriv->fullscreen) { 2321706f2543Smrg /* Fix up frame */ 2322706f2543Smrg pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; 2323706f2543Smrg pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; 2324706f2543Smrg pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; 2325706f2543Smrg pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; 2326706f2543Smrg 2327706f2543Smrg /* Fix up cursor */ 2328706f2543Smrg miPointerGetPosition(inputInfo.pointer, &px, &py); 2329706f2543Smrg if (px < pScrn->frameX0) px = pScrn->frameX0; 2330706f2543Smrg if (px > pScrn->frameX1) px = pScrn->frameX1; 2331706f2543Smrg if (py < pScrn->frameY0) py = pScrn->frameY0; 2332706f2543Smrg if (py > pScrn->frameY1) py = pScrn->frameY1; 2333706f2543Smrg pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE); 2334706f2543Smrg return; 2335706f2543Smrg } 2336706f2543Smrg 2337706f2543Smrg if (pDRIPriv->wrap.AdjustFrame) { 2338706f2543Smrg /* unwrap */ 2339706f2543Smrg pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; 2340706f2543Smrg /* call lower layers */ 2341706f2543Smrg (*pScrn->AdjustFrame)(scrnIndex, x, y, flags); 2342706f2543Smrg /* rewrap */ 2343706f2543Smrg pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; 2344706f2543Smrg pScrn->AdjustFrame = DRIAdjustFrame; 2345706f2543Smrg } 2346706f2543Smrg 2347706f2543Smrg _DRIAdjustFrame(pScrn, pDRIPriv, x, y); 2348706f2543Smrg} 2349706f2543Smrg 2350706f2543Smrg/* 2351706f2543Smrg * DRIMoveBuffersHelper swaps the regions rects in place leaving you 2352706f2543Smrg * a region with the rects in the order that you need to blit them, 2353706f2543Smrg * but it is possibly (likely) an invalid region afterwards. If you 2354706f2543Smrg * need to use the region again for anything you have to call 2355706f2543Smrg * REGION_VALIDATE on it, or better yet, save a copy first. 2356706f2543Smrg */ 2357706f2543Smrg 2358706f2543Smrgvoid 2359706f2543SmrgDRIMoveBuffersHelper( 2360706f2543Smrg ScreenPtr pScreen, 2361706f2543Smrg int dx, 2362706f2543Smrg int dy, 2363706f2543Smrg int *xdir, 2364706f2543Smrg int *ydir, 2365706f2543Smrg RegionPtr reg 2366706f2543Smrg) 2367706f2543Smrg{ 2368706f2543Smrg BoxPtr extents, pbox, firstBox, lastBox; 2369706f2543Smrg BoxRec tmpBox; 2370706f2543Smrg int y, nbox; 2371706f2543Smrg 2372706f2543Smrg extents = RegionExtents(reg); 2373706f2543Smrg nbox = RegionNumRects(reg); 2374706f2543Smrg pbox = RegionRects(reg); 2375706f2543Smrg 2376706f2543Smrg if((dy > 0) && (dy < (extents->y2 - extents->y1))) { 2377706f2543Smrg *ydir = -1; 2378706f2543Smrg if(nbox > 1) { 2379706f2543Smrg firstBox = pbox; 2380706f2543Smrg lastBox = pbox + nbox - 1; 2381706f2543Smrg while((unsigned long)firstBox < (unsigned long)lastBox) { 2382706f2543Smrg tmpBox = *firstBox; 2383706f2543Smrg *firstBox = *lastBox; 2384706f2543Smrg *lastBox = tmpBox; 2385706f2543Smrg firstBox++; 2386706f2543Smrg lastBox--; 2387706f2543Smrg } 2388706f2543Smrg } 2389706f2543Smrg } else *ydir = 1; 2390706f2543Smrg 2391706f2543Smrg if((dx > 0) && (dx < (extents->x2 - extents->x1))) { 2392706f2543Smrg *xdir = -1; 2393706f2543Smrg if(nbox > 1) { 2394706f2543Smrg firstBox = lastBox = pbox; 2395706f2543Smrg y = pbox->y1; 2396706f2543Smrg while(--nbox) { 2397706f2543Smrg pbox++; 2398706f2543Smrg if(pbox->y1 == y) lastBox++; 2399706f2543Smrg else { 2400706f2543Smrg while((unsigned long)firstBox < (unsigned long)lastBox) { 2401706f2543Smrg tmpBox = *firstBox; 2402706f2543Smrg *firstBox = *lastBox; 2403706f2543Smrg *lastBox = tmpBox; 2404706f2543Smrg firstBox++; 2405706f2543Smrg lastBox--; 2406706f2543Smrg } 2407706f2543Smrg 2408706f2543Smrg firstBox = lastBox = pbox; 2409706f2543Smrg y = pbox->y1; 2410706f2543Smrg } 2411706f2543Smrg } 2412706f2543Smrg while((unsigned long)firstBox < (unsigned long)lastBox) { 2413706f2543Smrg tmpBox = *firstBox; 2414706f2543Smrg *firstBox = *lastBox; 2415706f2543Smrg *lastBox = tmpBox; 2416706f2543Smrg firstBox++; 2417706f2543Smrg lastBox--; 2418706f2543Smrg } 2419706f2543Smrg } 2420706f2543Smrg } else *xdir = 1; 2421706f2543Smrg 2422706f2543Smrg} 2423706f2543Smrg 2424706f2543Smrgchar * 2425706f2543SmrgDRICreatePCIBusID(const struct pci_device * dev) 2426706f2543Smrg{ 2427706f2543Smrg char *busID; 2428706f2543Smrg 2429706f2543Smrg if (asprintf(&busID, "pci:%04x:%02x:%02x.%d", 2430706f2543Smrg dev->domain, dev->bus, dev->dev, dev->func) == -1) 2431706f2543Smrg return NULL; 2432706f2543Smrg 2433706f2543Smrg return busID; 2434706f2543Smrg} 2435706f2543Smrg 2436706f2543Smrgstatic void drmSIGIOHandler(int interrupt, void *closure) 2437706f2543Smrg{ 2438706f2543Smrg unsigned long key; 2439706f2543Smrg void *value; 2440706f2543Smrg ssize_t count; 2441706f2543Smrg drm_ctx_t ctx; 2442706f2543Smrg typedef void (*_drmCallback)(int, void *, void *); 2443706f2543Smrg char buf[256]; 2444706f2543Smrg drm_context_t old; 2445706f2543Smrg drm_context_t new; 2446706f2543Smrg void *oldctx; 2447706f2543Smrg void *newctx; 2448706f2543Smrg char *pt; 2449706f2543Smrg drmHashEntry *entry; 2450706f2543Smrg void *hash_table; 2451706f2543Smrg 2452706f2543Smrg hash_table = drmGetHashTable(); 2453706f2543Smrg 2454706f2543Smrg if (!hash_table) return; 2455706f2543Smrg if (drmHashFirst(hash_table, &key, &value)) { 2456706f2543Smrg entry = value; 2457706f2543Smrg do { 2458706f2543Smrg#if 0 2459706f2543Smrg fprintf(stderr, "Trying %d\n", entry->fd); 2460706f2543Smrg#endif 2461706f2543Smrg if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) { 2462706f2543Smrg buf[count] = '\0'; 2463706f2543Smrg#if 0 2464706f2543Smrg fprintf(stderr, "Got %s\n", buf); 2465706f2543Smrg#endif 2466706f2543Smrg 2467706f2543Smrg for (pt = buf; *pt != ' '; ++pt); /* Find first space */ 2468706f2543Smrg ++pt; 2469706f2543Smrg old = strtol(pt, &pt, 0); 2470706f2543Smrg new = strtol(pt, NULL, 0); 2471706f2543Smrg oldctx = drmGetContextTag(entry->fd, old); 2472706f2543Smrg newctx = drmGetContextTag(entry->fd, new); 2473706f2543Smrg#if 0 2474706f2543Smrg fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); 2475706f2543Smrg#endif 2476706f2543Smrg ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); 2477706f2543Smrg ctx.handle = new; 2478706f2543Smrg ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); 2479706f2543Smrg } 2480706f2543Smrg } while (drmHashNext(hash_table, &key, &value)); 2481706f2543Smrg } 2482706f2543Smrg} 2483706f2543Smrg 2484706f2543Smrg 2485706f2543Smrgint drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) 2486706f2543Smrg{ 2487706f2543Smrg drmHashEntry *entry; 2488706f2543Smrg 2489706f2543Smrg entry = drmGetEntry(fd); 2490706f2543Smrg entry->f = f; 2491706f2543Smrg 2492706f2543Smrg return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); 2493706f2543Smrg} 2494706f2543Smrg 2495706f2543Smrgint drmRemoveSIGIOHandler(int fd) 2496706f2543Smrg{ 2497706f2543Smrg drmHashEntry *entry = drmGetEntry(fd); 2498706f2543Smrg 2499706f2543Smrg entry->f = NULL; 2500706f2543Smrg 2501706f2543Smrg return xf86RemoveSIGIOHandler(fd); 2502706f2543Smrg} 2503