105b261ecSmrg/************************************************************************** 205b261ecSmrg 305b261ecSmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 405b261ecSmrgCopyright 2000 VA Linux Systems, Inc. 505b261ecSmrgAll Rights Reserved. 605b261ecSmrg 705b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a 805b261ecSmrgcopy of this software and associated documentation files (the 905b261ecSmrg"Software"), to deal in the Software without restriction, including 1005b261ecSmrgwithout limitation the rights to use, copy, modify, merge, publish, 1105b261ecSmrgdistribute, sub license, and/or sell copies of the Software, and to 1205b261ecSmrgpermit persons to whom the Software is furnished to do so, subject to 1305b261ecSmrgthe following conditions: 1405b261ecSmrg 1505b261ecSmrgThe above copyright notice and this permission notice (including the 1605b261ecSmrgnext paragraph) shall be included in all copies or substantial portions 1705b261ecSmrgof the Software. 1805b261ecSmrg 1905b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2005b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2105b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2205b261ecSmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 2305b261ecSmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2405b261ecSmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2505b261ecSmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2605b261ecSmrg 2705b261ecSmrg**************************************************************************/ 2805b261ecSmrg 2905b261ecSmrg/* 3005b261ecSmrg * Authors: 3105b261ecSmrg * Jens Owen <jens@tungstengraphics.com> 3205b261ecSmrg * Rickard E. (Rik) Faith <faith@valinux.com> 3305b261ecSmrg * 3405b261ecSmrg */ 3505b261ecSmrg 3605b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 3705b261ecSmrg#include <xorg-config.h> 3805b261ecSmrg#endif 3905b261ecSmrg 4005b261ecSmrg#include "xf86.h" 4105b261ecSmrg#include <sys/time.h> 4205b261ecSmrg#include <unistd.h> 4305b261ecSmrg#include <string.h> 4405b261ecSmrg#include <stdio.h> 4505b261ecSmrg#include <sys/ioctl.h> 4605b261ecSmrg#include <errno.h> 4705b261ecSmrg 4805b261ecSmrg#include <X11/X.h> 4905b261ecSmrg#include <X11/Xproto.h> 5005b261ecSmrg#include "xf86drm.h" 5105b261ecSmrg#include "misc.h" 5205b261ecSmrg#include "dixstruct.h" 5305b261ecSmrg#include "extnsionst.h" 5435c4bbdfSmrg#include "extinit.h" 5505b261ecSmrg#include "colormapst.h" 5605b261ecSmrg#include "cursorstr.h" 5705b261ecSmrg#include "scrnintstr.h" 5805b261ecSmrg#include "windowstr.h" 5905b261ecSmrg#include "servermd.h" 6005b261ecSmrg#define _XF86DRI_SERVER_ 616747b715Smrg#include <X11/dri/xf86driproto.h> 6205b261ecSmrg#include "swaprep.h" 6305b261ecSmrg#include "xf86str.h" 6405b261ecSmrg#include "dri.h" 6505b261ecSmrg#include "sarea.h" 6605b261ecSmrg#include "dristruct.h" 6705b261ecSmrg#include "mi.h" 6805b261ecSmrg#include "mipointer.h" 6905b261ecSmrg#include "xf86_OSproc.h" 704642e01fSmrg#include "inputstr.h" 716747b715Smrg#include "xf86VGAarbiter.h" 7235c4bbdfSmrg#include "xf86Extensions.h" 7305b261ecSmrg 7405b261ecSmrgstatic int DRIEntPrivIndex = -1; 756747b715Smrgstatic DevPrivateKeyRec DRIScreenPrivKeyRec; 7635c4bbdfSmrg 776747b715Smrg#define DRIScreenPrivKey (&DRIScreenPrivKeyRec) 786747b715Smrgstatic DevPrivateKeyRec DRIWindowPrivKeyRec; 7935c4bbdfSmrg 806747b715Smrg#define DRIWindowPrivKey (&DRIWindowPrivKeyRec) 8105b261ecSmrgstatic unsigned long DRIGeneration = 0; 8205b261ecSmrgstatic unsigned int DRIDrawableValidationStamp = 0; 8305b261ecSmrg 8405b261ecSmrgstatic RESTYPE DRIDrawablePrivResType; 8505b261ecSmrgstatic RESTYPE DRIContextPrivResType; 8635c4bbdfSmrgstatic void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); 8705b261ecSmrg 8805b261ecSmrgdrmServerInfo DRIDRMServerInfo; 8905b261ecSmrg 9035c4bbdfSmrg /* Wrapper just like xf86DrvMsg, but 9135c4bbdfSmrg without the verbosity level checking. 9235c4bbdfSmrg This will make it easy to turn off some 9335c4bbdfSmrg messages later, based on verbosity 9435c4bbdfSmrg level. */ 9505b261ecSmrg 9605b261ecSmrg/* 9705b261ecSmrg * Since we're already referencing things from the XFree86 common layer in 9805b261ecSmrg * this file, we'd might as well just call xf86VDrvMsgVerb, and have 9905b261ecSmrg * consistent message formatting. The verbosity of these messages can be 10005b261ecSmrg * easily changed here. 10105b261ecSmrg */ 10205b261ecSmrg#define DRI_MSG_VERBOSITY 1 10335c4bbdfSmrg 10435c4bbdfSmrgstatic void 10535c4bbdfSmrgDRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) 10635c4bbdfSmrg _X_ATTRIBUTE_PRINTF(3,4); 10735c4bbdfSmrg 10805b261ecSmrgstatic void 10905b261ecSmrgDRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) 11005b261ecSmrg{ 11135c4bbdfSmrg va_list ap; 11205b261ecSmrg 11305b261ecSmrg va_start(ap, format); 11405b261ecSmrg xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); 11505b261ecSmrg va_end(ap); 11605b261ecSmrg} 11705b261ecSmrg 11805b261ecSmrgstatic void 11905b261ecSmrgDRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv) 12005b261ecSmrg{ 12105b261ecSmrg if (pDRIEntPriv->pLSAREA != NULL) { 12235c4bbdfSmrg drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize); 12335c4bbdfSmrg pDRIEntPriv->pLSAREA = NULL; 12405b261ecSmrg } 12505b261ecSmrg if (pDRIEntPriv->hLSAREA != 0) { 12635c4bbdfSmrg drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA); 12705b261ecSmrg } 12805b261ecSmrg if (pDRIEntPriv->drmFD >= 0) { 12935c4bbdfSmrg drmClose(pDRIEntPriv->drmFD); 13035c4bbdfSmrg pDRIEntPriv->drmFD = 0; 13105b261ecSmrg } 13205b261ecSmrg} 13305b261ecSmrg 13405b261ecSmrgint 13505b261ecSmrgDRIMasterFD(ScrnInfoPtr pScrn) 13605b261ecSmrg{ 13705b261ecSmrg return DRI_ENT_PRIV(pScrn)->drmFD; 13805b261ecSmrg} 13905b261ecSmrg 14005b261ecSmrgvoid * 14105b261ecSmrgDRIMasterSareaPointer(ScrnInfoPtr pScrn) 14205b261ecSmrg{ 14305b261ecSmrg return DRI_ENT_PRIV(pScrn)->pLSAREA; 14405b261ecSmrg} 14505b261ecSmrg 14605b261ecSmrgdrm_handle_t 14705b261ecSmrgDRIMasterSareaHandle(ScrnInfoPtr pScrn) 14805b261ecSmrg{ 14905b261ecSmrg return DRI_ENT_PRIV(pScrn)->hLSAREA; 15005b261ecSmrg} 15105b261ecSmrg 15205b261ecSmrgBool 15305b261ecSmrgDRIOpenDRMMaster(ScrnInfoPtr pScrn, 15435c4bbdfSmrg unsigned long sAreaSize, 15535c4bbdfSmrg const char *busID, const char *drmDriverName) 15605b261ecSmrg{ 15705b261ecSmrg drmSetVersion saveSv, sv; 15805b261ecSmrg Bool drmWasAvailable; 15905b261ecSmrg DRIEntPrivPtr pDRIEntPriv; 16005b261ecSmrg DRIEntPrivRec tmp; 16105b261ecSmrg int count; 16205b261ecSmrg int err; 16305b261ecSmrg 16405b261ecSmrg if (DRIEntPrivIndex == -1) 16535c4bbdfSmrg DRIEntPrivIndex = xf86AllocateEntityPrivateIndex(); 16605b261ecSmrg 16705b261ecSmrg pDRIEntPriv = DRI_ENT_PRIV(pScrn); 16805b261ecSmrg 16905b261ecSmrg if (pDRIEntPriv && pDRIEntPriv->drmFD != -1) 17035c4bbdfSmrg return TRUE; 17105b261ecSmrg 17205b261ecSmrg drmWasAvailable = drmAvailable(); 17305b261ecSmrg 17405b261ecSmrg memset(&tmp, 0, sizeof(tmp)); 17505b261ecSmrg 17605b261ecSmrg tmp.drmFD = -1; 17705b261ecSmrg sv.drm_di_major = 1; 17805b261ecSmrg sv.drm_di_minor = 1; 17905b261ecSmrg sv.drm_dd_major = -1; 18005b261ecSmrg 18105b261ecSmrg saveSv = sv; 18205b261ecSmrg count = 10; 18305b261ecSmrg while (count--) { 1841b5d61b8Smrg tmp.drmFD = drmOpen(drmDriverName, busID); 18505b261ecSmrg 18635c4bbdfSmrg if (tmp.drmFD < 0) { 18735c4bbdfSmrg DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n"); 18835c4bbdfSmrg goto out_err; 18935c4bbdfSmrg } 19005b261ecSmrg 19135c4bbdfSmrg err = drmSetInterfaceVersion(tmp.drmFD, &sv); 19205b261ecSmrg 19335c4bbdfSmrg if (err != -EPERM) 19435c4bbdfSmrg break; 19505b261ecSmrg 19635c4bbdfSmrg sv = saveSv; 19735c4bbdfSmrg drmClose(tmp.drmFD); 19835c4bbdfSmrg tmp.drmFD = -1; 19935c4bbdfSmrg usleep(100000); 20005b261ecSmrg } 20105b261ecSmrg 20205b261ecSmrg if (tmp.drmFD <= 0) { 20335c4bbdfSmrg DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n"); 20435c4bbdfSmrg goto out_err; 20505b261ecSmrg } 20605b261ecSmrg 20705b261ecSmrg if (!drmWasAvailable) { 20835c4bbdfSmrg DRIDrvMsg(-1, X_INFO, 20935c4bbdfSmrg "[drm] loaded kernel module for \"%s\" driver.\n", 21035c4bbdfSmrg drmDriverName); 21105b261ecSmrg } 21205b261ecSmrg 21305b261ecSmrg if (err != 0) { 21435c4bbdfSmrg sv.drm_di_major = 1; 21535c4bbdfSmrg sv.drm_di_minor = 0; 21605b261ecSmrg } 21705b261ecSmrg 21805b261ecSmrg DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n", 21935c4bbdfSmrg sv.drm_di_major, sv.drm_di_minor); 22005b261ecSmrg 22105b261ecSmrg if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1) 22235c4bbdfSmrg err = 0; 22305b261ecSmrg else 22435c4bbdfSmrg err = drmSetBusid(tmp.drmFD, busID); 22505b261ecSmrg 22605b261ecSmrg if (err) { 22735c4bbdfSmrg DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n"); 22835c4bbdfSmrg goto out_err; 22905b261ecSmrg } 23005b261ecSmrg 23105b261ecSmrg /* 23205b261ecSmrg * Create a lock-containing sarea. 23305b261ecSmrg */ 23405b261ecSmrg 23535c4bbdfSmrg if (drmAddMap(tmp.drmFD, 0, sAreaSize, DRM_SHM, 23635c4bbdfSmrg DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) { 23705b261ecSmrg DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n"); 23835c4bbdfSmrg tmp.hLSAREA = 0; 23935c4bbdfSmrg goto out_err; 24005b261ecSmrg } 24105b261ecSmrg 24235c4bbdfSmrg if (drmMap(tmp.drmFD, tmp.hLSAREA, sAreaSize, 24335c4bbdfSmrg (drmAddressPtr) (&tmp.pLSAREA)) < 0) { 24405b261ecSmrg DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n"); 24535c4bbdfSmrg tmp.pLSAREA = NULL; 24635c4bbdfSmrg goto out_err; 24705b261ecSmrg } 24805b261ecSmrg 24905b261ecSmrg memset(tmp.pLSAREA, 0, sAreaSize); 25005b261ecSmrg 25105b261ecSmrg /* 25205b261ecSmrg * Reserved contexts are handled by the first opened screen. 25305b261ecSmrg */ 25405b261ecSmrg 25505b261ecSmrg tmp.resOwner = NULL; 25605b261ecSmrg 25705b261ecSmrg if (!pDRIEntPriv) 25835c4bbdfSmrg pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1); 25905b261ecSmrg 26005b261ecSmrg if (!pDRIEntPriv) { 26105b261ecSmrg DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for " 26235c4bbdfSmrg "DRM device.\n"); 26335c4bbdfSmrg goto out_err; 26405b261ecSmrg } 26505b261ecSmrg *pDRIEntPriv = tmp; 26635c4bbdfSmrg xf86GetEntityPrivate((pScrn)->entityList[0], DRIEntPrivIndex)->ptr = 26735c4bbdfSmrg pDRIEntPriv; 26805b261ecSmrg 26905b261ecSmrg DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n"); 27005b261ecSmrg return TRUE; 27105b261ecSmrg 27235c4bbdfSmrg out_err: 27305b261ecSmrg 27405b261ecSmrg DRIOpenDRMCleanup(&tmp); 27505b261ecSmrg return FALSE; 27605b261ecSmrg} 27705b261ecSmrg 2784642e01fSmrgstatic void 27935c4bbdfSmrg DRIClipNotifyAllDrawables(ScreenPtr pScreen); 2804642e01fSmrg 2814642e01fSmrgstatic void 2824642e01fSmrgdri_crtc_notify(ScreenPtr pScreen) 2834642e01fSmrg{ 28435c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 28535c4bbdfSmrg 2864642e01fSmrg DRIClipNotifyAllDrawables(pScreen); 2874642e01fSmrg xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); 2884642e01fSmrg xf86_crtc_notify(pScreen); 28935c4bbdfSmrg pDRIPriv->xf86_crtc_notify = 29035c4bbdfSmrg xf86_wrap_crtc_notify(pScreen, dri_crtc_notify); 2914642e01fSmrg} 29205b261ecSmrg 2931b5d61b8Smrgstatic void 2941b5d61b8SmrgdrmSIGIOHandler(int interrupt, void *closure) 2951b5d61b8Smrg{ 2961b5d61b8Smrg unsigned long key; 2971b5d61b8Smrg void *value; 2981b5d61b8Smrg ssize_t count; 2991b5d61b8Smrg drm_ctx_t ctx; 3001b5d61b8Smrg typedef void (*_drmCallback) (int, void *, void *); 3011b5d61b8Smrg char buf[256]; 3021b5d61b8Smrg drm_context_t old; 3031b5d61b8Smrg drm_context_t new; 3041b5d61b8Smrg void *oldctx; 3051b5d61b8Smrg void *newctx; 3061b5d61b8Smrg char *pt; 3071b5d61b8Smrg drmHashEntry *entry; 3081b5d61b8Smrg void *hash_table; 3091b5d61b8Smrg 3101b5d61b8Smrg hash_table = drmGetHashTable(); 3111b5d61b8Smrg 3121b5d61b8Smrg if (!hash_table) 3131b5d61b8Smrg return; 3141b5d61b8Smrg if (drmHashFirst(hash_table, &key, &value)) { 3151b5d61b8Smrg entry = value; 3161b5d61b8Smrg do { 3171b5d61b8Smrg if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) { 3181b5d61b8Smrg buf[count] = '\0'; 3191b5d61b8Smrg 3201b5d61b8Smrg for (pt = buf; *pt != ' '; ++pt); /* Find first space */ 3211b5d61b8Smrg ++pt; 3221b5d61b8Smrg old = strtol(pt, &pt, 0); 3231b5d61b8Smrg new = strtol(pt, NULL, 0); 3241b5d61b8Smrg oldctx = drmGetContextTag(entry->fd, old); 3251b5d61b8Smrg newctx = drmGetContextTag(entry->fd, new); 3261b5d61b8Smrg ((_drmCallback) entry->f) (entry->fd, oldctx, newctx); 3271b5d61b8Smrg ctx.handle = new; 3281b5d61b8Smrg ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); 3291b5d61b8Smrg } 3301b5d61b8Smrg } while (drmHashNext(hash_table, &key, &value)); 3311b5d61b8Smrg } 3321b5d61b8Smrg} 3331b5d61b8Smrg 3341b5d61b8Smrgstatic int 3351b5d61b8SmrgdrmInstallSIGIOHandler(int fd, void (*f) (int, void *, void *)) 3361b5d61b8Smrg{ 3371b5d61b8Smrg drmHashEntry *entry; 3381b5d61b8Smrg 3391b5d61b8Smrg entry = drmGetEntry(fd); 3401b5d61b8Smrg entry->f = f; 3411b5d61b8Smrg 3421b5d61b8Smrg return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); 3431b5d61b8Smrg} 3441b5d61b8Smrg 3451b5d61b8Smrgstatic int 3461b5d61b8SmrgdrmRemoveSIGIOHandler(int fd) 3471b5d61b8Smrg{ 3481b5d61b8Smrg drmHashEntry *entry = drmGetEntry(fd); 3491b5d61b8Smrg 3501b5d61b8Smrg entry->f = NULL; 3511b5d61b8Smrg 3521b5d61b8Smrg return xf86RemoveSIGIOHandler(fd); 3531b5d61b8Smrg} 3541b5d61b8Smrg 35505b261ecSmrgBool 35605b261ecSmrgDRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) 35705b261ecSmrg{ 35835c4bbdfSmrg DRIScreenPrivPtr pDRIPriv; 35935c4bbdfSmrg drm_context_t *reserved; 36035c4bbdfSmrg int reserved_count; 36135c4bbdfSmrg int i; 36235c4bbdfSmrg DRIEntPrivPtr pDRIEntPriv; 36335c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 36435c4bbdfSmrg DRIContextFlags flags = 0; 36535c4bbdfSmrg DRIContextPrivPtr pDRIContextPriv; 36635c4bbdfSmrg static Bool drm_server_inited; 36705b261ecSmrg 36805b261ecSmrg /* If the DRI extension is disabled, do not initialize the DRI */ 36905b261ecSmrg if (noXFree86DRIExtension) { 37035c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_WARNING, 37135c4bbdfSmrg "Direct rendering has been disabled.\n"); 37235c4bbdfSmrg return FALSE; 37305b261ecSmrg } 37405b261ecSmrg 3756747b715Smrg if (!xf86VGAarbiterAllowDRI(pScreen)) { 3766747b715Smrg DRIDrvMsg(pScreen->myNum, X_WARNING, 3776747b715Smrg "Direct rendering is not supported when VGA arb is necessary for the device\n"); 37835c4bbdfSmrg return FALSE; 3796747b715Smrg } 3806747b715Smrg 3816747b715Smrg#ifdef PANORAMIX 38205b261ecSmrg /* 38305b261ecSmrg * If Xinerama is on, don't allow DRI to initialise. It won't be usable 38405b261ecSmrg * anyway. 38505b261ecSmrg */ 38635c4bbdfSmrg if (!noPanoramiXExtension) { 38735c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_WARNING, 38835c4bbdfSmrg "Direct rendering is not supported when Xinerama is enabled\n"); 38935c4bbdfSmrg return FALSE; 39035c4bbdfSmrg } 3916747b715Smrg#endif 39235c4bbdfSmrg if (drm_server_inited == FALSE) { 39335c4bbdfSmrg drmSetServerInfo(&DRIDRMServerInfo); 39435c4bbdfSmrg drm_server_inited = TRUE; 39535c4bbdfSmrg } 39605b261ecSmrg 39705b261ecSmrg if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize, 39835c4bbdfSmrg pDRIInfo->busIdString, pDRIInfo->drmDriverName)) 39935c4bbdfSmrg return FALSE; 40005b261ecSmrg 40105b261ecSmrg pDRIEntPriv = DRI_ENT_PRIV(pScrn); 40205b261ecSmrg 4034642e01fSmrg if (DRIGeneration != serverGeneration) 40435c4bbdfSmrg DRIGeneration = serverGeneration; 40505b261ecSmrg 4066747b715Smrg if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0)) 40735c4bbdfSmrg return FALSE; 4086747b715Smrg if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0)) 40935c4bbdfSmrg return FALSE; 4106747b715Smrg 4116747b715Smrg pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); 41205b261ecSmrg if (!pDRIPriv) { 41335c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 41405b261ecSmrg return FALSE; 41505b261ecSmrg } 41605b261ecSmrg 4174642e01fSmrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); 41805b261ecSmrg pDRIPriv->drmFD = pDRIEntPriv->drmFD; 41905b261ecSmrg pDRIPriv->directRenderingSupport = TRUE; 42005b261ecSmrg pDRIPriv->pDriverInfo = pDRIInfo; 42105b261ecSmrg pDRIPriv->nrWindows = 0; 42205b261ecSmrg pDRIPriv->nrWindowsVisible = 0; 42305b261ecSmrg pDRIPriv->fullscreen = NULL; 42405b261ecSmrg 42535c4bbdfSmrg pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; 42605b261ecSmrg pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; 42705b261ecSmrg 42805b261ecSmrg pDRIPriv->grabbedDRILock = FALSE; 42905b261ecSmrg pDRIPriv->drmSIGIOHandlerInstalled = FALSE; 43005b261ecSmrg *pDRMFD = pDRIPriv->drmFD; 43105b261ecSmrg 43205b261ecSmrg if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) { 43305b261ecSmrg 43435c4bbdfSmrg if (drmAddMap(pDRIPriv->drmFD, 43535c4bbdfSmrg 0, 43635c4bbdfSmrg pDRIPriv->pDriverInfo->SAREASize, 43735c4bbdfSmrg DRM_SHM, 0, &pDRIPriv->hSAREA) < 0) { 43835c4bbdfSmrg pDRIPriv->directRenderingSupport = FALSE; 43935c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 44035c4bbdfSmrg drmClose(pDRIPriv->drmFD); 44135c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] drmAddMap failed\n"); 44235c4bbdfSmrg return FALSE; 44335c4bbdfSmrg } 44435c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 44535c4bbdfSmrg "[drm] added %d byte SAREA at %p\n", 44635c4bbdfSmrg (int) pDRIPriv->pDriverInfo->SAREASize, (void *) (uintptr_t) pDRIPriv->hSAREA); 44735c4bbdfSmrg 44835c4bbdfSmrg /* Backwards compat. */ 44935c4bbdfSmrg if (drmMap(pDRIPriv->drmFD, 45035c4bbdfSmrg pDRIPriv->hSAREA, 45135c4bbdfSmrg pDRIPriv->pDriverInfo->SAREASize, 45235c4bbdfSmrg (drmAddressPtr) (&pDRIPriv->pSAREA)) < 0) { 45335c4bbdfSmrg pDRIPriv->directRenderingSupport = FALSE; 45435c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 45535c4bbdfSmrg drmClose(pDRIPriv->drmFD); 45635c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] drmMap failed\n"); 45735c4bbdfSmrg return FALSE; 45835c4bbdfSmrg } 45935c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", 46035c4bbdfSmrg (void *) (uintptr_t) pDRIPriv->hSAREA, pDRIPriv->pSAREA); 46135c4bbdfSmrg memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); 46235c4bbdfSmrg } 46335c4bbdfSmrg else { 46435c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock " 46535c4bbdfSmrg "SAREA also for drawables.\n"); 46635c4bbdfSmrg pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA; 46735c4bbdfSmrg pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA; 46835c4bbdfSmrg pDRIEntPriv->sAreaGrabbed = TRUE; 46905b261ecSmrg } 47005b261ecSmrg 47105b261ecSmrg pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA; 47205b261ecSmrg pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA; 47305b261ecSmrg 47435c4bbdfSmrg if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer) { 47535c4bbdfSmrg if (drmAddMap(pDRIPriv->drmFD, 47635c4bbdfSmrg (uintptr_t) pDRIPriv->pDriverInfo-> 47735c4bbdfSmrg frameBufferPhysicalAddress, 47835c4bbdfSmrg pDRIPriv->pDriverInfo->frameBufferSize, DRM_FRAME_BUFFER, 47935c4bbdfSmrg 0, &pDRIPriv->pDriverInfo->hFrameBuffer) < 0) { 48035c4bbdfSmrg pDRIPriv->directRenderingSupport = FALSE; 48135c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 48235c4bbdfSmrg drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); 48335c4bbdfSmrg drmClose(pDRIPriv->drmFD); 48435c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] drmAddMap failed\n"); 48535c4bbdfSmrg return FALSE; 48635c4bbdfSmrg } 48735c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", 48835c4bbdfSmrg (void *) (uintptr_t) pDRIPriv->pDriverInfo->hFrameBuffer); 48935c4bbdfSmrg } 49035c4bbdfSmrg else { 49135c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 49235c4bbdfSmrg "[drm] framebuffer mapped by ddx driver\n"); 49305b261ecSmrg } 49405b261ecSmrg 49505b261ecSmrg if (pDRIEntPriv->resOwner == NULL) { 49635c4bbdfSmrg pDRIEntPriv->resOwner = pScreen; 49735c4bbdfSmrg 49835c4bbdfSmrg /* Add tags for reserved contexts */ 49935c4bbdfSmrg if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, 50035c4bbdfSmrg &reserved_count))) { 50135c4bbdfSmrg int r; 50235c4bbdfSmrg void *tag; 50335c4bbdfSmrg 50435c4bbdfSmrg for (r = 0; r < reserved_count; r++) { 50535c4bbdfSmrg tag = DRICreateContextPrivFromHandle(pScreen, 50635c4bbdfSmrg reserved[r], 50735c4bbdfSmrg DRI_CONTEXT_RESERVED); 50835c4bbdfSmrg drmAddContextTag(pDRIPriv->drmFD, reserved[r], tag); 50935c4bbdfSmrg } 51035c4bbdfSmrg drmFreeReservedContextList(reserved); 51135c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 51235c4bbdfSmrg "[drm] added %d reserved context%s for kernel\n", 51335c4bbdfSmrg reserved_count, reserved_count > 1 ? "s" : ""); 51435c4bbdfSmrg } 51505b261ecSmrg } 51605b261ecSmrg 51705b261ecSmrg /* validate max drawable table entry set by driver */ 51805b261ecSmrg if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || 51905b261ecSmrg (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { 52035c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 52135c4bbdfSmrg "Invalid max drawable table size set by driver: %d\n", 52235c4bbdfSmrg pDRIPriv->pDriverInfo->maxDrawableTableEntry); 52305b261ecSmrg } 52405b261ecSmrg 52505b261ecSmrg /* Initialize drawable tables (screen private and SAREA) */ 52635c4bbdfSmrg for (i = 0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { 52735c4bbdfSmrg pDRIPriv->DRIDrawables[i] = NULL; 52835c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[i].stamp = 0; 52935c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[i].flags = 0; 53005b261ecSmrg } 53105b261ecSmrg 53205b261ecSmrg pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount; 53305b261ecSmrg pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext; 53405b261ecSmrg 53505b261ecSmrg if (!pDRIEntPriv->keepFDOpen) 53635c4bbdfSmrg pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen; 53705b261ecSmrg 53805b261ecSmrg pDRIEntPriv->refCount++; 53905b261ecSmrg 54005b261ecSmrg /* Set up flags for DRICreateContextPriv */ 54105b261ecSmrg switch (pDRIInfo->driverSwapMethod) { 54205b261ecSmrg case DRI_KERNEL_SWAP: 54335c4bbdfSmrg flags = DRI_CONTEXT_2DONLY; 54435c4bbdfSmrg break; 54505b261ecSmrg case DRI_HIDE_X_CONTEXT: 54635c4bbdfSmrg flags = DRI_CONTEXT_PRESERVED; 54735c4bbdfSmrg break; 54805b261ecSmrg } 54905b261ecSmrg 55005b261ecSmrg if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, 55135c4bbdfSmrg &pDRIPriv->myContext, 55235c4bbdfSmrg flags))) { 55335c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, "failed to create server context\n"); 55435c4bbdfSmrg return FALSE; 55505b261ecSmrg } 55605b261ecSmrg pDRIPriv->myContextPriv = pDRIContextPriv; 55705b261ecSmrg 55805b261ecSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 55935c4bbdfSmrg "X context handle = %p\n", (void *) (uintptr_t) pDRIPriv->myContext); 56005b261ecSmrg 56105b261ecSmrg /* Now that we have created the X server's context, we can grab the 56205b261ecSmrg * hardware lock for the X server. 56305b261ecSmrg */ 56405b261ecSmrg DRILock(pScreen, 0); 56505b261ecSmrg pDRIPriv->grabbedDRILock = TRUE; 56605b261ecSmrg 56705b261ecSmrg /* pointers so that we can prevent memory leaks later */ 56835c4bbdfSmrg pDRIPriv->hiddenContextStore = NULL; 56905b261ecSmrg pDRIPriv->partial3DContextStore = NULL; 57005b261ecSmrg 57135c4bbdfSmrg switch (pDRIInfo->driverSwapMethod) { 57205b261ecSmrg case DRI_HIDE_X_CONTEXT: 57335c4bbdfSmrg /* Server will handle 3D swaps, and hide 2D swaps from kernel. 57435c4bbdfSmrg * Register server context as a preserved context. 57535c4bbdfSmrg */ 57635c4bbdfSmrg 57735c4bbdfSmrg /* allocate memory for hidden context store */ 57835c4bbdfSmrg pDRIPriv->hiddenContextStore 57935c4bbdfSmrg = (void *) calloc(1, pDRIInfo->contextSize); 58035c4bbdfSmrg if (!pDRIPriv->hiddenContextStore) { 58135c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 58235c4bbdfSmrg "failed to allocate hidden context\n"); 58335c4bbdfSmrg DRIDestroyContextPriv(pDRIContextPriv); 58435c4bbdfSmrg return FALSE; 58535c4bbdfSmrg } 58635c4bbdfSmrg 58735c4bbdfSmrg /* allocate memory for partial 3D context store */ 58835c4bbdfSmrg pDRIPriv->partial3DContextStore 58935c4bbdfSmrg = (void *) calloc(1, pDRIInfo->contextSize); 59035c4bbdfSmrg if (!pDRIPriv->partial3DContextStore) { 59135c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 59235c4bbdfSmrg "[DRI] failed to allocate partial 3D context\n"); 59335c4bbdfSmrg free(pDRIPriv->hiddenContextStore); 59435c4bbdfSmrg DRIDestroyContextPriv(pDRIContextPriv); 59535c4bbdfSmrg return FALSE; 59635c4bbdfSmrg } 59735c4bbdfSmrg 59835c4bbdfSmrg /* save initial context store */ 59935c4bbdfSmrg if (pDRIInfo->SwapContext) { 60035c4bbdfSmrg (*pDRIInfo->SwapContext) (pScreen, 60135c4bbdfSmrg DRI_NO_SYNC, 60235c4bbdfSmrg DRI_2D_CONTEXT, 60335c4bbdfSmrg pDRIPriv->hiddenContextStore, 60435c4bbdfSmrg DRI_NO_CONTEXT, NULL); 60535c4bbdfSmrg } 60635c4bbdfSmrg /* fall through */ 60705b261ecSmrg 60805b261ecSmrg case DRI_SERVER_SWAP: 60905b261ecSmrg /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT 61005b261ecSmrg * setup signal handler for receiving swap requests from kernel 61135c4bbdfSmrg */ 61235c4bbdfSmrg if (!(pDRIPriv->drmSIGIOHandlerInstalled = 61335c4bbdfSmrg drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { 61435c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 61535c4bbdfSmrg "[drm] failed to setup DRM signal handler\n"); 61635c4bbdfSmrg free(pDRIPriv->hiddenContextStore); 61735c4bbdfSmrg free(pDRIPriv->partial3DContextStore); 61835c4bbdfSmrg DRIDestroyContextPriv(pDRIContextPriv); 61935c4bbdfSmrg return FALSE; 62035c4bbdfSmrg } 62135c4bbdfSmrg else { 62235c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 62335c4bbdfSmrg "[drm] installed DRM signal handler\n"); 62435c4bbdfSmrg } 62505b261ecSmrg 62605b261ecSmrg default: 62735c4bbdfSmrg break; 62805b261ecSmrg } 62905b261ecSmrg 63005b261ecSmrg return TRUE; 63105b261ecSmrg} 63205b261ecSmrg 63305b261ecSmrgBool 63405b261ecSmrgDRIFinishScreenInit(ScreenPtr pScreen) 63505b261ecSmrg{ 63635c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 63735c4bbdfSmrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 63805b261ecSmrg 63905b261ecSmrg /* Wrap DRI support */ 64005b261ecSmrg if (pDRIInfo->wrap.WindowExposures) { 64135c4bbdfSmrg pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 64235c4bbdfSmrg pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; 64305b261ecSmrg } 64405b261ecSmrg 64535c4bbdfSmrg pDRIPriv->DestroyWindow = pScreen->DestroyWindow; 64635c4bbdfSmrg pScreen->DestroyWindow = DRIDestroyWindow; 64705b261ecSmrg 6484642e01fSmrg pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, 64935c4bbdfSmrg dri_crtc_notify); 65035c4bbdfSmrg 65105b261ecSmrg if (pDRIInfo->wrap.CopyWindow) { 65235c4bbdfSmrg pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 65335c4bbdfSmrg pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; 65405b261ecSmrg } 65505b261ecSmrg if (pDRIInfo->wrap.ClipNotify) { 65635c4bbdfSmrg pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 65735c4bbdfSmrg pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; 65805b261ecSmrg } 65905b261ecSmrg if (pDRIInfo->wrap.AdjustFrame) { 66035c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 66135c4bbdfSmrg 66235c4bbdfSmrg pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; 66335c4bbdfSmrg pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; 66405b261ecSmrg } 66505b261ecSmrg pDRIPriv->wrapped = TRUE; 66605b261ecSmrg 66705b261ecSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); 66805b261ecSmrg 66905b261ecSmrg return TRUE; 67005b261ecSmrg} 67105b261ecSmrg 67205b261ecSmrgvoid 67305b261ecSmrgDRICloseScreen(ScreenPtr pScreen) 67405b261ecSmrg{ 67505b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 67635c4bbdfSmrg DRIInfoPtr pDRIInfo; 67735c4bbdfSmrg drm_context_t *reserved; 67835c4bbdfSmrg int reserved_count; 67935c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 68035c4bbdfSmrg DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn); 68105b261ecSmrg Bool closeMaster; 68205b261ecSmrg 68305b261ecSmrg if (pDRIPriv) { 68405b261ecSmrg 68505b261ecSmrg pDRIInfo = pDRIPriv->pDriverInfo; 68605b261ecSmrg 68735c4bbdfSmrg if (pDRIPriv->wrapped) { 68835c4bbdfSmrg /* Unwrap DRI Functions */ 68935c4bbdfSmrg if (pDRIInfo->wrap.WindowExposures) { 69035c4bbdfSmrg pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 69135c4bbdfSmrg pDRIPriv->wrap.WindowExposures = NULL; 69235c4bbdfSmrg } 69335c4bbdfSmrg if (pDRIPriv->DestroyWindow) { 69435c4bbdfSmrg pScreen->DestroyWindow = pDRIPriv->DestroyWindow; 69535c4bbdfSmrg pDRIPriv->DestroyWindow = NULL; 69635c4bbdfSmrg } 69735c4bbdfSmrg 69835c4bbdfSmrg xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); 69935c4bbdfSmrg 70035c4bbdfSmrg if (pDRIInfo->wrap.CopyWindow) { 70135c4bbdfSmrg pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 70235c4bbdfSmrg pDRIPriv->wrap.CopyWindow = NULL; 70335c4bbdfSmrg } 70435c4bbdfSmrg if (pDRIInfo->wrap.ClipNotify) { 70535c4bbdfSmrg pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 70635c4bbdfSmrg pDRIPriv->wrap.ClipNotify = NULL; 70735c4bbdfSmrg } 70835c4bbdfSmrg if (pDRIInfo->wrap.AdjustFrame) { 70935c4bbdfSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 71035c4bbdfSmrg 71135c4bbdfSmrg scrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; 71235c4bbdfSmrg pDRIPriv->wrap.AdjustFrame = NULL; 71335c4bbdfSmrg } 71435c4bbdfSmrg 71535c4bbdfSmrg pDRIPriv->wrapped = FALSE; 71635c4bbdfSmrg } 71735c4bbdfSmrg 71835c4bbdfSmrg if (pDRIPriv->drmSIGIOHandlerInstalled) { 71935c4bbdfSmrg if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { 72035c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 72135c4bbdfSmrg "[drm] failed to remove DRM signal handler\n"); 72235c4bbdfSmrg } 72335c4bbdfSmrg } 72405b261ecSmrg 72505b261ecSmrg if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { 72635c4bbdfSmrg DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); 72735c4bbdfSmrg } 72835c4bbdfSmrg 72935c4bbdfSmrg if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { 73035c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 73135c4bbdfSmrg "failed to destroy server context\n"); 73235c4bbdfSmrg } 73335c4bbdfSmrg 73435c4bbdfSmrg /* Remove tags for reserved contexts */ 73535c4bbdfSmrg if (pDRIEntPriv->resOwner == pScreen) { 73635c4bbdfSmrg pDRIEntPriv->resOwner = NULL; 73735c4bbdfSmrg 73835c4bbdfSmrg if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, 73935c4bbdfSmrg &reserved_count))) { 74035c4bbdfSmrg int i; 74135c4bbdfSmrg 74235c4bbdfSmrg for (i = 0; i < reserved_count; i++) { 74335c4bbdfSmrg DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, 74435c4bbdfSmrg reserved[i])); 74535c4bbdfSmrg } 74635c4bbdfSmrg drmFreeReservedContextList(reserved); 74735c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 74835c4bbdfSmrg "[drm] removed %d reserved context%s for kernel\n", 74935c4bbdfSmrg reserved_count, reserved_count > 1 ? "s" : ""); 75035c4bbdfSmrg } 75135c4bbdfSmrg } 75235c4bbdfSmrg 75335c4bbdfSmrg /* Make sure signals get unblocked etc. */ 75435c4bbdfSmrg drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); 75535c4bbdfSmrg pDRIPriv->pLockRefCount = NULL; 75635c4bbdfSmrg closeMaster = (--pDRIEntPriv->refCount == 0) && 75735c4bbdfSmrg !pDRIEntPriv->keepFDOpen; 75835c4bbdfSmrg if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) { 75935c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 76035c4bbdfSmrg "[drm] unmapping %d bytes of SAREA %p at %p\n", 76135c4bbdfSmrg (int) pDRIInfo->SAREASize, (void *) (uintptr_t) pDRIPriv->hSAREA, pDRIPriv->pSAREA); 76235c4bbdfSmrg if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { 76335c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 76435c4bbdfSmrg "[drm] unable to unmap %d bytes" 76535c4bbdfSmrg " of SAREA %p at %p\n", 76635c4bbdfSmrg (int) pDRIInfo->SAREASize, 76735c4bbdfSmrg (void *) (uintptr_t) pDRIPriv->hSAREA, pDRIPriv->pSAREA); 76835c4bbdfSmrg } 76935c4bbdfSmrg } 77035c4bbdfSmrg else { 77135c4bbdfSmrg pDRIEntPriv->sAreaGrabbed = FALSE; 77235c4bbdfSmrg } 77335c4bbdfSmrg 77435c4bbdfSmrg if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) { 77535c4bbdfSmrg drmClose(pDRIPriv->drmFD); 77635c4bbdfSmrg if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) { 77735c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Closed DRM master.\n"); 77835c4bbdfSmrg pDRIEntPriv->drmFD = -1; 77935c4bbdfSmrg } 78035c4bbdfSmrg } 78135c4bbdfSmrg 78235c4bbdfSmrg free(pDRIPriv); 78335c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 78405b261ecSmrg } 78505b261ecSmrg} 78605b261ecSmrg 78705b261ecSmrg#define DRM_MSG_VERBOSITY 3 78805b261ecSmrg 78935c4bbdfSmrgstatic int 79035c4bbdfSmrgdri_drm_debug_print(const char *format, va_list ap) 79135c4bbdfSmrg _X_ATTRIBUTE_PRINTF(1,0); 79235c4bbdfSmrg 79335c4bbdfSmrgstatic int 79435c4bbdfSmrgdri_drm_debug_print(const char *format, va_list ap) 79505b261ecSmrg{ 79635c4bbdfSmrg xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); 79735c4bbdfSmrg return 0; 79805b261ecSmrg} 79905b261ecSmrg 80035c4bbdfSmrgstatic void 80135c4bbdfSmrgdri_drm_get_perms(gid_t * group, mode_t * mode) 80205b261ecSmrg{ 80335c4bbdfSmrg *group = xf86ConfigDRI.group; 80435c4bbdfSmrg *mode = xf86ConfigDRI.mode; 80505b261ecSmrg} 80605b261ecSmrg 80735c4bbdfSmrgdrmServerInfo DRIDRMServerInfo = { 80835c4bbdfSmrg dri_drm_debug_print, 80935c4bbdfSmrg xf86LoadKernelModule, 81035c4bbdfSmrg dri_drm_get_perms, 81105b261ecSmrg}; 81205b261ecSmrg 81305b261ecSmrgBool 81405b261ecSmrgDRIExtensionInit(void) 81505b261ecSmrg{ 8166747b715Smrg if (DRIGeneration != serverGeneration) { 81735c4bbdfSmrg return FALSE; 81805b261ecSmrg } 81905b261ecSmrg 8206747b715Smrg DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, 82135c4bbdfSmrg "DRIDrawable"); 8226747b715Smrg DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete, 82335c4bbdfSmrg "DRIContext"); 8246747b715Smrg 8256747b715Smrg if (!DRIDrawablePrivResType || !DRIContextPrivResType) 82635c4bbdfSmrg return FALSE; 82705b261ecSmrg 82805b261ecSmrg RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); 82905b261ecSmrg 83005b261ecSmrg return TRUE; 83105b261ecSmrg} 83205b261ecSmrg 83305b261ecSmrgvoid 83405b261ecSmrgDRIReset(void) 83505b261ecSmrg{ 83605b261ecSmrg /* 83705b261ecSmrg * This stub routine is called when the X Server recycles, resources 83805b261ecSmrg * allocated by DRIExtensionInit need to be managed here. 83905b261ecSmrg * 84005b261ecSmrg * Currently this routine is a stub because all the interesting resources 84105b261ecSmrg * are managed via the screen init process. 84205b261ecSmrg */ 84305b261ecSmrg} 84405b261ecSmrg 84505b261ecSmrgBool 84635c4bbdfSmrgDRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool *isCapable) 84705b261ecSmrg{ 84805b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 84905b261ecSmrg 85005b261ecSmrg if (pDRIPriv) 85135c4bbdfSmrg *isCapable = pDRIPriv->directRenderingSupport; 85205b261ecSmrg else 85335c4bbdfSmrg *isCapable = FALSE; 85405b261ecSmrg 85505b261ecSmrg return TRUE; 85605b261ecSmrg} 85705b261ecSmrg 85805b261ecSmrgBool 85905b261ecSmrgDRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) 86005b261ecSmrg{ 86105b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 86205b261ecSmrg 86335c4bbdfSmrg *hSAREA = pDRIPriv->hSAREA; 86435c4bbdfSmrg *busIdString = pDRIPriv->pDriverInfo->busIdString; 86505b261ecSmrg 86605b261ecSmrg return TRUE; 86705b261ecSmrg} 86805b261ecSmrg 86905b261ecSmrgBool 87005b261ecSmrgDRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) 87105b261ecSmrg{ 87205b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 87305b261ecSmrg 87435c4bbdfSmrg if (drmAuthMagic(pDRIPriv->drmFD, magic)) 87535c4bbdfSmrg return FALSE; 87605b261ecSmrg return TRUE; 87705b261ecSmrg} 87805b261ecSmrg 87905b261ecSmrgBool 88005b261ecSmrgDRICloseConnection(ScreenPtr pScreen) 88105b261ecSmrg{ 88205b261ecSmrg return TRUE; 88305b261ecSmrg} 88405b261ecSmrg 88505b261ecSmrgBool 88605b261ecSmrgDRIGetClientDriverName(ScreenPtr pScreen, 88705b261ecSmrg int *ddxDriverMajorVersion, 88805b261ecSmrg int *ddxDriverMinorVersion, 88935c4bbdfSmrg int *ddxDriverPatchVersion, char **clientDriverName) 89005b261ecSmrg{ 89105b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 89205b261ecSmrg 89305b261ecSmrg *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; 89405b261ecSmrg *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; 89505b261ecSmrg *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; 89635c4bbdfSmrg *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; 89705b261ecSmrg 89805b261ecSmrg return TRUE; 89905b261ecSmrg} 90005b261ecSmrg 90105b261ecSmrg/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper 90205b261ecSmrg functions that layer on drmCreateContext and drmAddContextTag. 90305b261ecSmrg 90405b261ecSmrg DRICreateContextPriv always creates a kernel drm_context_t and then calls 90505b261ecSmrg DRICreateContextPrivFromHandle to create a DRIContextPriv structure for 90605b261ecSmrg DRI tracking. For the SIGIO handler, the drm_context_t is associated with 90705b261ecSmrg DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv 90805b261ecSmrg area and are passed to the kernel (if necessary). 90905b261ecSmrg 91005b261ecSmrg DRICreateContextPriv returns a pointer to newly allocated 91105b261ecSmrg DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ 91205b261ecSmrg 91305b261ecSmrgDRIContextPrivPtr 91405b261ecSmrgDRICreateContextPriv(ScreenPtr pScreen, 91535c4bbdfSmrg drm_context_t * pHWContext, DRIContextFlags flags) 91605b261ecSmrg{ 91735c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 91805b261ecSmrg 91905b261ecSmrg if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { 92035c4bbdfSmrg return NULL; 92105b261ecSmrg } 92205b261ecSmrg 92305b261ecSmrg return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); 92405b261ecSmrg} 92505b261ecSmrg 92605b261ecSmrgDRIContextPrivPtr 92705b261ecSmrgDRICreateContextPrivFromHandle(ScreenPtr pScreen, 92835c4bbdfSmrg drm_context_t hHWContext, DRIContextFlags flags) 92905b261ecSmrg{ 93035c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 93105b261ecSmrg DRIContextPrivPtr pDRIContextPriv; 93235c4bbdfSmrg int contextPrivSize; 93305b261ecSmrg 93405b261ecSmrg contextPrivSize = sizeof(DRIContextPrivRec) + 93535c4bbdfSmrg pDRIPriv->pDriverInfo->contextSize; 9366747b715Smrg if (!(pDRIContextPriv = calloc(1, contextPrivSize))) { 93735c4bbdfSmrg return NULL; 93805b261ecSmrg } 93935c4bbdfSmrg pDRIContextPriv->pContextStore = (void *) (pDRIContextPriv + 1); 94005b261ecSmrg 94105b261ecSmrg drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); 94205b261ecSmrg 94305b261ecSmrg pDRIContextPriv->hwContext = hHWContext; 94435c4bbdfSmrg pDRIContextPriv->pScreen = pScreen; 94535c4bbdfSmrg pDRIContextPriv->flags = flags; 94635c4bbdfSmrg pDRIContextPriv->valid3D = FALSE; 94705b261ecSmrg 94805b261ecSmrg if (flags & DRI_CONTEXT_2DONLY) { 94935c4bbdfSmrg if (drmSetContextFlags(pDRIPriv->drmFD, hHWContext, DRM_CONTEXT_2DONLY)) { 95035c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 95135c4bbdfSmrg "[drm] failed to set 2D context flag\n"); 95235c4bbdfSmrg DRIDestroyContextPriv(pDRIContextPriv); 95335c4bbdfSmrg return NULL; 95435c4bbdfSmrg } 95505b261ecSmrg } 95605b261ecSmrg if (flags & DRI_CONTEXT_PRESERVED) { 95735c4bbdfSmrg if (drmSetContextFlags(pDRIPriv->drmFD, 95835c4bbdfSmrg hHWContext, DRM_CONTEXT_PRESERVED)) { 95935c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 96035c4bbdfSmrg "[drm] failed to set preserved flag\n"); 96135c4bbdfSmrg DRIDestroyContextPriv(pDRIContextPriv); 96235c4bbdfSmrg return NULL; 96335c4bbdfSmrg } 96405b261ecSmrg } 96505b261ecSmrg return pDRIContextPriv; 96605b261ecSmrg} 96705b261ecSmrg 96805b261ecSmrgBool 96905b261ecSmrgDRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) 97005b261ecSmrg{ 97105b261ecSmrg DRIScreenPrivPtr pDRIPriv; 97205b261ecSmrg 97335c4bbdfSmrg if (!pDRIContextPriv) 97435c4bbdfSmrg return TRUE; 97505b261ecSmrg 97605b261ecSmrg pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); 97705b261ecSmrg 97805b261ecSmrg if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { 97935c4bbdfSmrg /* Don't delete reserved contexts from 98035c4bbdfSmrg kernel area -- the kernel manages its 98135c4bbdfSmrg reserved contexts itself. */ 98235c4bbdfSmrg if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) 98335c4bbdfSmrg return FALSE; 98435c4bbdfSmrg } 98535c4bbdfSmrg 98635c4bbdfSmrg /* Remove the tag last to prevent a race 98735c4bbdfSmrg condition where the context has pending 98835c4bbdfSmrg buffers. The context can't be re-used 98935c4bbdfSmrg while in this thread, but buffers can be 99035c4bbdfSmrg dispatched asynchronously. */ 99105b261ecSmrg drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); 9926747b715Smrg free(pDRIContextPriv); 99305b261ecSmrg return TRUE; 99405b261ecSmrg} 99505b261ecSmrg 99605b261ecSmrgstatic Bool 99705b261ecSmrgDRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) 99805b261ecSmrg{ 99905b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 100005b261ecSmrg DRIContextPrivPtr pDRIContextPriv; 100105b261ecSmrg void *contextStore; 100205b261ecSmrg 100305b261ecSmrg if (!(pDRIContextPriv = 100435c4bbdfSmrg DRICreateContextPriv(pScreen, &pDRIPriv->pSAREA->dummy_context, 0))) { 100535c4bbdfSmrg return FALSE; 100605b261ecSmrg } 100705b261ecSmrg 100805b261ecSmrg contextStore = DRIGetContextStore(pDRIContextPriv); 100905b261ecSmrg if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { 101035c4bbdfSmrg if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL, 101135c4bbdfSmrg pDRIPriv->pSAREA-> 101235c4bbdfSmrg dummy_context, NULL, 101335c4bbdfSmrg (DRIContextType) (long) 101435c4bbdfSmrg contextStore)) { 101535c4bbdfSmrg DRIDestroyContextPriv(pDRIContextPriv); 101635c4bbdfSmrg return FALSE; 101735c4bbdfSmrg } 101805b261ecSmrg } 101905b261ecSmrg 102005b261ecSmrg pDRIPriv->dummyCtxPriv = pDRIContextPriv; 102105b261ecSmrg return TRUE; 102205b261ecSmrg} 102305b261ecSmrg 102405b261ecSmrgstatic void 102505b261ecSmrgDRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) 102605b261ecSmrg{ 102705b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 102805b261ecSmrg DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; 102905b261ecSmrg void *contextStore; 103005b261ecSmrg 103135c4bbdfSmrg if (!pDRIContextPriv) 103235c4bbdfSmrg return; 103305b261ecSmrg if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { 103435c4bbdfSmrg contextStore = DRIGetContextStore(pDRIContextPriv); 103535c4bbdfSmrg pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, 103635c4bbdfSmrg pDRIContextPriv->hwContext, 103735c4bbdfSmrg (DRIContextType) (long) 103835c4bbdfSmrg contextStore); 103905b261ecSmrg } 104005b261ecSmrg 104105b261ecSmrg DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); 104205b261ecSmrg pDRIPriv->dummyCtxPriv = NULL; 104305b261ecSmrg} 104405b261ecSmrg 104505b261ecSmrgBool 104605b261ecSmrgDRICreateContext(ScreenPtr pScreen, VisualPtr visual, 104705b261ecSmrg XID context, drm_context_t * pHWContext) 104805b261ecSmrg{ 104905b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 105005b261ecSmrg DRIContextPrivPtr pDRIContextPriv; 105105b261ecSmrg void *contextStore; 105205b261ecSmrg 105305b261ecSmrg if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { 105405b261ecSmrg if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { 105535c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 105635c4bbdfSmrg "[drm] Could not create dummy context\n"); 105735c4bbdfSmrg return FALSE; 105835c4bbdfSmrg } 105905b261ecSmrg } 106005b261ecSmrg 106105b261ecSmrg if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { 106235c4bbdfSmrg return FALSE; 106305b261ecSmrg } 106405b261ecSmrg 106505b261ecSmrg contextStore = DRIGetContextStore(pDRIContextPriv); 106605b261ecSmrg if (pDRIPriv->pDriverInfo->CreateContext) { 106735c4bbdfSmrg if (!((*pDRIPriv->pDriverInfo->CreateContext) (pScreen, NULL, 106835c4bbdfSmrg *pHWContext, NULL, 106935c4bbdfSmrg (DRIContextType) (long) 107035c4bbdfSmrg contextStore))) { 107135c4bbdfSmrg DRIDestroyContextPriv(pDRIContextPriv); 107235c4bbdfSmrg return FALSE; 107335c4bbdfSmrg } 107405b261ecSmrg } 107505b261ecSmrg 107605b261ecSmrg /* track this in case the client dies before cleanup */ 107735c4bbdfSmrg if (!AddResource(context, DRIContextPrivResType, (void *) pDRIContextPriv)) 107835c4bbdfSmrg return FALSE; 107905b261ecSmrg 108005b261ecSmrg return TRUE; 108105b261ecSmrg} 108205b261ecSmrg 108305b261ecSmrgBool 108405b261ecSmrgDRIDestroyContext(ScreenPtr pScreen, XID context) 108505b261ecSmrg{ 108605b261ecSmrg FreeResourceByType(context, DRIContextPrivResType, FALSE); 108705b261ecSmrg 108805b261ecSmrg return TRUE; 108905b261ecSmrg} 109005b261ecSmrg 109105b261ecSmrg/* DRIContextPrivDelete is called by the resource manager. */ 109205b261ecSmrgBool 109335c4bbdfSmrgDRIContextPrivDelete(void *pResource, XID id) 109405b261ecSmrg{ 109535c4bbdfSmrg DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr) pResource; 109605b261ecSmrg DRIScreenPrivPtr pDRIPriv; 109705b261ecSmrg void *contextStore; 109805b261ecSmrg 109905b261ecSmrg pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); 110005b261ecSmrg if (pDRIPriv->pDriverInfo->DestroyContext) { 110135c4bbdfSmrg contextStore = DRIGetContextStore(pDRIContextPriv); 110235c4bbdfSmrg pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, 110335c4bbdfSmrg pDRIContextPriv->hwContext, 110435c4bbdfSmrg (DRIContextType) (long) 110535c4bbdfSmrg contextStore); 110605b261ecSmrg } 110705b261ecSmrg return DRIDestroyContextPriv(pDRIContextPriv); 110805b261ecSmrg} 110905b261ecSmrg 111005b261ecSmrg/* This walks the drawable timestamp array and invalidates all of them 111105b261ecSmrg * in the case of transition from private to shared backbuffers. It's 111205b261ecSmrg * not necessary for correctness, because DRIClipNotify gets called in 111305b261ecSmrg * time to prevent any conflict, but the transition from 111405b261ecSmrg * shared->private is sometimes missed if we don't do this. 111505b261ecSmrg */ 111605b261ecSmrgstatic void 111705b261ecSmrgDRIClipNotifyAllDrawables(ScreenPtr pScreen) 111805b261ecSmrg{ 111935c4bbdfSmrg int i; 112035c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 112105b261ecSmrg 112235c4bbdfSmrg for (i = 0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { 112335c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; 112435c4bbdfSmrg } 112505b261ecSmrg} 112605b261ecSmrg 112705b261ecSmrgstatic void 112805b261ecSmrgDRITransitionToSharedBuffers(ScreenPtr pScreen) 112905b261ecSmrg{ 113005b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 113105b261ecSmrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 113205b261ecSmrg 113335c4bbdfSmrg DRIClipNotifyAllDrawables(pScreen); 113405b261ecSmrg 113505b261ecSmrg if (pDRIInfo->TransitionSingleToMulti3D) 113635c4bbdfSmrg pDRIInfo->TransitionSingleToMulti3D(pScreen); 113705b261ecSmrg} 113805b261ecSmrg 113905b261ecSmrgstatic void 114005b261ecSmrgDRITransitionToPrivateBuffers(ScreenPtr pScreen) 114105b261ecSmrg{ 114205b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 114305b261ecSmrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 114405b261ecSmrg 114535c4bbdfSmrg DRIClipNotifyAllDrawables(pScreen); 114605b261ecSmrg 114705b261ecSmrg if (pDRIInfo->TransitionMultiToSingle3D) 114835c4bbdfSmrg pDRIInfo->TransitionMultiToSingle3D(pScreen); 114905b261ecSmrg} 115005b261ecSmrg 115105b261ecSmrgstatic void 115205b261ecSmrgDRITransitionTo3d(ScreenPtr pScreen) 115305b261ecSmrg{ 115405b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 115505b261ecSmrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 115605b261ecSmrg 115735c4bbdfSmrg DRIClipNotifyAllDrawables(pScreen); 115805b261ecSmrg 115905b261ecSmrg if (pDRIInfo->TransitionTo3d) 116035c4bbdfSmrg pDRIInfo->TransitionTo3d(pScreen); 116105b261ecSmrg} 116205b261ecSmrg 116305b261ecSmrgstatic void 116405b261ecSmrgDRITransitionTo2d(ScreenPtr pScreen) 116505b261ecSmrg{ 116605b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 116705b261ecSmrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 116805b261ecSmrg 116935c4bbdfSmrg DRIClipNotifyAllDrawables(pScreen); 117005b261ecSmrg 117105b261ecSmrg if (pDRIInfo->TransitionTo2d) 117235c4bbdfSmrg pDRIInfo->TransitionTo2d(pScreen); 117305b261ecSmrg} 117405b261ecSmrg 117505b261ecSmrgstatic int 117635c4bbdfSmrgDRIDCNTreeTraversal(WindowPtr pWin, void *data) 117705b261ecSmrg{ 117805b261ecSmrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 117905b261ecSmrg 118005b261ecSmrg if (pDRIDrawablePriv) { 118135c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 118235c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 118305b261ecSmrg 118435c4bbdfSmrg if (RegionNumRects(&pWin->clipList) > 0) { 118535c4bbdfSmrg WindowPtr *pDRIWindows = (WindowPtr *) data; 118635c4bbdfSmrg int i = 0; 118705b261ecSmrg 118835c4bbdfSmrg while (pDRIWindows[i]) 118935c4bbdfSmrg i++; 119005b261ecSmrg 119135c4bbdfSmrg pDRIWindows[i] = pWin; 119205b261ecSmrg 119335c4bbdfSmrg pDRIPriv->nrWalked++; 119435c4bbdfSmrg } 119505b261ecSmrg 119635c4bbdfSmrg if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) 119735c4bbdfSmrg return WT_STOPWALKING; 119805b261ecSmrg } 119905b261ecSmrg 120005b261ecSmrg return WT_WALKCHILDREN; 120105b261ecSmrg} 120205b261ecSmrg 120305b261ecSmrgstatic void 120405b261ecSmrgDRIDriverClipNotify(ScreenPtr pScreen) 120505b261ecSmrg{ 120605b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 120705b261ecSmrg 120805b261ecSmrg if (pDRIPriv->pDriverInfo->ClipNotify) { 120935c4bbdfSmrg WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows); 121035c4bbdfSmrg DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 121105b261ecSmrg 121235c4bbdfSmrg if (pDRIPriv->nrWindows > 0) { 121335c4bbdfSmrg pDRIPriv->nrWalked = 0; 121435c4bbdfSmrg TraverseTree(pScreen->root, DRIDCNTreeTraversal, 121535c4bbdfSmrg (void *) pDRIWindows); 121635c4bbdfSmrg } 121705b261ecSmrg 121835c4bbdfSmrg pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows); 121905b261ecSmrg 122035c4bbdfSmrg free(pDRIWindows); 122105b261ecSmrg } 122205b261ecSmrg} 122305b261ecSmrg 122405b261ecSmrgstatic void 122505b261ecSmrgDRIIncreaseNumberVisible(ScreenPtr pScreen) 122605b261ecSmrg{ 122705b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 122805b261ecSmrg 122905b261ecSmrg switch (++pDRIPriv->nrWindowsVisible) { 123005b261ecSmrg case 1: 123135c4bbdfSmrg DRITransitionTo3d(pScreen); 123235c4bbdfSmrg break; 123305b261ecSmrg case 2: 123435c4bbdfSmrg DRITransitionToSharedBuffers(pScreen); 123535c4bbdfSmrg break; 123605b261ecSmrg default: 123735c4bbdfSmrg break; 123805b261ecSmrg } 123905b261ecSmrg 124005b261ecSmrg DRIDriverClipNotify(pScreen); 124105b261ecSmrg} 124205b261ecSmrg 124305b261ecSmrgstatic void 124405b261ecSmrgDRIDecreaseNumberVisible(ScreenPtr pScreen) 124505b261ecSmrg{ 124605b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 124705b261ecSmrg 124805b261ecSmrg switch (--pDRIPriv->nrWindowsVisible) { 124905b261ecSmrg case 0: 125035c4bbdfSmrg DRITransitionTo2d(pScreen); 125135c4bbdfSmrg break; 125205b261ecSmrg case 1: 125335c4bbdfSmrg DRITransitionToPrivateBuffers(pScreen); 125435c4bbdfSmrg break; 125505b261ecSmrg default: 125635c4bbdfSmrg break; 125705b261ecSmrg } 125805b261ecSmrg 125905b261ecSmrg DRIDriverClipNotify(pScreen); 126005b261ecSmrg} 126105b261ecSmrg 126205b261ecSmrgBool 126305b261ecSmrgDRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable, 126435c4bbdfSmrg drm_drawable_t * hHWDrawable) 126505b261ecSmrg{ 126635c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 126735c4bbdfSmrg DRIDrawablePrivPtr pDRIDrawablePriv; 126835c4bbdfSmrg WindowPtr pWin; 126905b261ecSmrg 127005b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 127135c4bbdfSmrg pWin = (WindowPtr) pDrawable; 127235c4bbdfSmrg if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 127335c4bbdfSmrg pDRIDrawablePriv->refCount++; 127435c4bbdfSmrg 127535c4bbdfSmrg if (!pDRIDrawablePriv->hwDrawable) { 127635c4bbdfSmrg drmCreateDrawable(pDRIPriv->drmFD, 127735c4bbdfSmrg &pDRIDrawablePriv->hwDrawable); 127835c4bbdfSmrg } 127935c4bbdfSmrg } 128035c4bbdfSmrg else { 128135c4bbdfSmrg /* allocate a DRI Window Private record */ 128235c4bbdfSmrg if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) { 128335c4bbdfSmrg return FALSE; 128435c4bbdfSmrg } 128535c4bbdfSmrg 128635c4bbdfSmrg /* Only create a drm_drawable_t once */ 128735c4bbdfSmrg if (drmCreateDrawable(pDRIPriv->drmFD, 128835c4bbdfSmrg &pDRIDrawablePriv->hwDrawable)) { 128935c4bbdfSmrg free(pDRIDrawablePriv); 129035c4bbdfSmrg return FALSE; 129135c4bbdfSmrg } 129235c4bbdfSmrg 129335c4bbdfSmrg /* add it to the list of DRI drawables for this screen */ 129435c4bbdfSmrg pDRIDrawablePriv->pScreen = pScreen; 129535c4bbdfSmrg pDRIDrawablePriv->refCount = 1; 129635c4bbdfSmrg pDRIDrawablePriv->drawableIndex = -1; 129735c4bbdfSmrg pDRIDrawablePriv->nrects = RegionNumRects(&pWin->clipList); 129835c4bbdfSmrg 129935c4bbdfSmrg /* save private off of preallocated index */ 130035c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, 130135c4bbdfSmrg pDRIDrawablePriv); 130235c4bbdfSmrg pDRIPriv->nrWindows++; 130335c4bbdfSmrg 130435c4bbdfSmrg if (pDRIDrawablePriv->nrects) 130535c4bbdfSmrg DRIIncreaseNumberVisible(pScreen); 130635c4bbdfSmrg } 130735c4bbdfSmrg 130835c4bbdfSmrg /* track this in case the client dies */ 130935c4bbdfSmrg if (!AddResource(FakeClientID(client->index), DRIDrawablePrivResType, 131035c4bbdfSmrg (void *) (intptr_t) pDrawable->id)) 131135c4bbdfSmrg return FALSE; 131235c4bbdfSmrg 131335c4bbdfSmrg if (pDRIDrawablePriv->hwDrawable) { 131435c4bbdfSmrg drmUpdateDrawableInfo(pDRIPriv->drmFD, 131535c4bbdfSmrg pDRIDrawablePriv->hwDrawable, 131635c4bbdfSmrg DRM_DRAWABLE_CLIPRECTS, 131735c4bbdfSmrg RegionNumRects(&pWin->clipList), 131835c4bbdfSmrg RegionRects(&pWin->clipList)); 131935c4bbdfSmrg *hHWDrawable = pDRIDrawablePriv->hwDrawable; 132035c4bbdfSmrg } 132135c4bbdfSmrg } 132235c4bbdfSmrg else if (pDrawable->type != DRAWABLE_PIXMAP) { /* PBuffer */ 132335c4bbdfSmrg /* NOT_DONE */ 132435c4bbdfSmrg return FALSE; 132505b261ecSmrg } 132605b261ecSmrg 132705b261ecSmrg return TRUE; 132805b261ecSmrg} 132905b261ecSmrg 133005b261ecSmrgstatic void 133105b261ecSmrgDRIDrawablePrivDestroy(WindowPtr pWin) 133205b261ecSmrg{ 133305b261ecSmrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 133405b261ecSmrg ScreenPtr pScreen; 133505b261ecSmrg DRIScreenPrivPtr pDRIPriv; 133605b261ecSmrg 133705b261ecSmrg if (!pDRIDrawablePriv) 133835c4bbdfSmrg return; 133905b261ecSmrg 134005b261ecSmrg pScreen = pWin->drawable.pScreen; 134105b261ecSmrg pDRIPriv = DRI_SCREEN_PRIV(pScreen); 134205b261ecSmrg 134305b261ecSmrg if (pDRIDrawablePriv->drawableIndex != -1) { 134435c4bbdfSmrg /* bump stamp to force outstanding 3D requests to resync */ 134535c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp 134635c4bbdfSmrg = DRIDrawableValidationStamp++; 134705b261ecSmrg 134835c4bbdfSmrg /* release drawable table entry */ 134935c4bbdfSmrg pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; 135005b261ecSmrg } 135105b261ecSmrg 135205b261ecSmrg pDRIPriv->nrWindows--; 135305b261ecSmrg 135405b261ecSmrg if (pDRIDrawablePriv->nrects) 135535c4bbdfSmrg DRIDecreaseNumberVisible(pScreen); 135605b261ecSmrg 135705b261ecSmrg drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable); 135805b261ecSmrg 13596747b715Smrg free(pDRIDrawablePriv); 13604642e01fSmrg dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); 136105b261ecSmrg} 136205b261ecSmrg 136305b261ecSmrgstatic Bool 136435c4bbdfSmrgDRIDestroyDrawableCB(void *value, XID id, void *data) 136505b261ecSmrg{ 136605b261ecSmrg if (value == data) { 136735c4bbdfSmrg /* This calls back DRIDrawablePrivDelete which frees private area */ 136835c4bbdfSmrg FreeResourceByType(id, DRIDrawablePrivResType, FALSE); 136905b261ecSmrg 137035c4bbdfSmrg return TRUE; 137105b261ecSmrg } 137205b261ecSmrg 137305b261ecSmrg return FALSE; 137405b261ecSmrg} 137505b261ecSmrg 137605b261ecSmrgBool 137705b261ecSmrgDRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable) 137805b261ecSmrg{ 137905b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 138035c4bbdfSmrg LookupClientResourceComplex(client, DRIDrawablePrivResType, 138135c4bbdfSmrg DRIDestroyDrawableCB, 138235c4bbdfSmrg (void *) (intptr_t) pDrawable->id); 138305b261ecSmrg } 138435c4bbdfSmrg else { /* pixmap (or for GLX 1.3, a PBuffer) */ 138535c4bbdfSmrg /* NOT_DONE */ 138635c4bbdfSmrg return FALSE; 138705b261ecSmrg } 138805b261ecSmrg 138905b261ecSmrg return TRUE; 139005b261ecSmrg} 139105b261ecSmrg 139205b261ecSmrgBool 139335c4bbdfSmrgDRIDrawablePrivDelete(void *pResource, XID id) 139405b261ecSmrg{ 139505b261ecSmrg WindowPtr pWin; 13966747b715Smrg int rc; 139705b261ecSmrg 13986747b715Smrg /* For DRIDrawablePrivResType, the XID is the client's fake ID. The 13996747b715Smrg * important XID is the value in pResource. */ 140035c4bbdfSmrg id = (XID) (intptr_t) pResource; 14016747b715Smrg rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess); 140205b261ecSmrg 14036747b715Smrg if (rc == Success) { 140435c4bbdfSmrg DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 140505b261ecSmrg 140635c4bbdfSmrg if (!pDRIDrwPriv) 140735c4bbdfSmrg return FALSE; 140805b261ecSmrg 140935c4bbdfSmrg if (--pDRIDrwPriv->refCount == 0) 141035c4bbdfSmrg DRIDrawablePrivDestroy(pWin); 141105b261ecSmrg 141235c4bbdfSmrg return TRUE; 141305b261ecSmrg } 141435c4bbdfSmrg else { /* pixmap (or for GLX 1.3, a PBuffer) */ 141535c4bbdfSmrg /* NOT_DONE */ 141635c4bbdfSmrg return FALSE; 141705b261ecSmrg } 141805b261ecSmrg} 141905b261ecSmrg 142005b261ecSmrgBool 142105b261ecSmrgDRIGetDrawableInfo(ScreenPtr pScreen, 142205b261ecSmrg DrawablePtr pDrawable, 142335c4bbdfSmrg unsigned int *index, 142435c4bbdfSmrg unsigned int *stamp, 142535c4bbdfSmrg int *X, 142635c4bbdfSmrg int *Y, 142735c4bbdfSmrg int *W, 142835c4bbdfSmrg int *H, 142935c4bbdfSmrg int *numClipRects, 143005b261ecSmrg drm_clip_rect_t ** pClipRects, 143135c4bbdfSmrg int *backX, 143235c4bbdfSmrg int *backY, 143335c4bbdfSmrg int *numBackClipRects, drm_clip_rect_t ** pBackClipRects) 143405b261ecSmrg{ 143535c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 143635c4bbdfSmrg DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; 143735c4bbdfSmrg WindowPtr pWin, pOldWin; 143835c4bbdfSmrg int i; 143905b261ecSmrg 144005b261ecSmrg#if 0 144135c4bbdfSmrg printf("maxDrawableTableEntry = %d\n", 144235c4bbdfSmrg pDRIPriv->pDriverInfo->maxDrawableTableEntry); 144305b261ecSmrg#endif 144405b261ecSmrg 144505b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 144635c4bbdfSmrg pWin = (WindowPtr) pDrawable; 144735c4bbdfSmrg if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 144835c4bbdfSmrg 144935c4bbdfSmrg /* Manage drawable table */ 145035c4bbdfSmrg if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ 145135c4bbdfSmrg 145235c4bbdfSmrg /* Search table for empty entry */ 145335c4bbdfSmrg i = 0; 145435c4bbdfSmrg while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { 145535c4bbdfSmrg if (!(pDRIPriv->DRIDrawables[i])) { 145635c4bbdfSmrg pDRIPriv->DRIDrawables[i] = pDrawable; 145735c4bbdfSmrg pDRIDrawablePriv->drawableIndex = i; 145835c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[i].stamp = 145935c4bbdfSmrg DRIDrawableValidationStamp++; 146035c4bbdfSmrg break; 146135c4bbdfSmrg } 146235c4bbdfSmrg i++; 146335c4bbdfSmrg } 146435c4bbdfSmrg 146535c4bbdfSmrg /* Search table for oldest entry */ 146635c4bbdfSmrg if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { 146705b261ecSmrg unsigned int oldestStamp = ~0; 146805b261ecSmrg int oldestIndex = 0; 146935c4bbdfSmrg 147035c4bbdfSmrg i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; 147135c4bbdfSmrg while (i--) { 147235c4bbdfSmrg if (pDRIPriv->pSAREA->drawableTable[i].stamp < 147335c4bbdfSmrg oldestStamp) { 147435c4bbdfSmrg oldestIndex = i; 147535c4bbdfSmrg oldestStamp = 147635c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[i].stamp; 147735c4bbdfSmrg } 147835c4bbdfSmrg } 147935c4bbdfSmrg pDRIDrawablePriv->drawableIndex = oldestIndex; 148035c4bbdfSmrg 148135c4bbdfSmrg /* release oldest drawable table entry */ 148235c4bbdfSmrg pOldWin = (WindowPtr) pDRIPriv->DRIDrawables[oldestIndex]; 148335c4bbdfSmrg pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); 148435c4bbdfSmrg pOldDrawPriv->drawableIndex = -1; 148535c4bbdfSmrg 148635c4bbdfSmrg /* claim drawable table entry */ 148735c4bbdfSmrg pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; 148835c4bbdfSmrg 148935c4bbdfSmrg /* validate SAREA entry */ 149035c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = 149135c4bbdfSmrg DRIDrawableValidationStamp++; 149235c4bbdfSmrg 149335c4bbdfSmrg /* check for stamp wrap around */ 149435c4bbdfSmrg if (oldestStamp > DRIDrawableValidationStamp) { 149535c4bbdfSmrg 149635c4bbdfSmrg /* walk SAREA table and invalidate all drawables */ 149735c4bbdfSmrg for (i = 0; 149805b261ecSmrg i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; 149905b261ecSmrg i++) { 150035c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[i].stamp = 150135c4bbdfSmrg DRIDrawableValidationStamp++; 150235c4bbdfSmrg } 150335c4bbdfSmrg } 150435c4bbdfSmrg } 150535c4bbdfSmrg 150635c4bbdfSmrg /* If the driver wants to be notified when the index is 150735c4bbdfSmrg * set for a drawable, let it know now. 150835c4bbdfSmrg */ 150935c4bbdfSmrg if (pDRIPriv->pDriverInfo->SetDrawableIndex) 151035c4bbdfSmrg pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, 151135c4bbdfSmrg pDRIDrawablePriv-> 151235c4bbdfSmrg drawableIndex); 151335c4bbdfSmrg 151435c4bbdfSmrg /* reinit drawable ID if window is visible */ 151535c4bbdfSmrg if ((pWin->viewable) && 151635c4bbdfSmrg (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) { 151735c4bbdfSmrg (*pDRIPriv->pDriverInfo->InitBuffers) (pWin, 151835c4bbdfSmrg &pWin->clipList, 151935c4bbdfSmrg pDRIDrawablePriv-> 152035c4bbdfSmrg drawableIndex); 152135c4bbdfSmrg } 152235c4bbdfSmrg } 152335c4bbdfSmrg 152435c4bbdfSmrg *index = pDRIDrawablePriv->drawableIndex; 152535c4bbdfSmrg *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; 152635c4bbdfSmrg *X = (int) (pWin->drawable.x); 152735c4bbdfSmrg *Y = (int) (pWin->drawable.y); 152835c4bbdfSmrg *W = (int) (pWin->drawable.width); 152935c4bbdfSmrg *H = (int) (pWin->drawable.height); 153035c4bbdfSmrg *numClipRects = RegionNumRects(&pWin->clipList); 153135c4bbdfSmrg *pClipRects = (drm_clip_rect_t *) RegionRects(&pWin->clipList); 153235c4bbdfSmrg 153335c4bbdfSmrg if (!*numClipRects && pDRIPriv->fullscreen) { 153435c4bbdfSmrg /* use fake full-screen clip rect */ 153535c4bbdfSmrg pDRIPriv->fullscreen_rect.x1 = *X; 153635c4bbdfSmrg pDRIPriv->fullscreen_rect.y1 = *Y; 153735c4bbdfSmrg pDRIPriv->fullscreen_rect.x2 = *X + *W; 153835c4bbdfSmrg pDRIPriv->fullscreen_rect.y2 = *Y + *H; 153935c4bbdfSmrg 154035c4bbdfSmrg *numClipRects = 1; 154135c4bbdfSmrg *pClipRects = &pDRIPriv->fullscreen_rect; 154235c4bbdfSmrg } 154335c4bbdfSmrg 154435c4bbdfSmrg *backX = *X; 154535c4bbdfSmrg *backY = *Y; 154635c4bbdfSmrg 154735c4bbdfSmrg if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) { 154835c4bbdfSmrg /* Use a single cliprect. */ 154935c4bbdfSmrg 155035c4bbdfSmrg int x0 = *X; 155135c4bbdfSmrg int y0 = *Y; 155235c4bbdfSmrg int x1 = x0 + *W; 155335c4bbdfSmrg int y1 = y0 + *H; 155435c4bbdfSmrg 155535c4bbdfSmrg if (x0 < 0) 155635c4bbdfSmrg x0 = 0; 155735c4bbdfSmrg if (y0 < 0) 155835c4bbdfSmrg y0 = 0; 155935c4bbdfSmrg if (x1 > pScreen->width) 156035c4bbdfSmrg x1 = pScreen->width; 156135c4bbdfSmrg if (y1 > pScreen->height) 156235c4bbdfSmrg y1 = pScreen->height; 156335c4bbdfSmrg 156435c4bbdfSmrg if (y0 >= y1 || x0 >= x1) { 156535c4bbdfSmrg *numBackClipRects = 0; 156635c4bbdfSmrg *pBackClipRects = NULL; 156735c4bbdfSmrg } 156835c4bbdfSmrg else { 156935c4bbdfSmrg pDRIPriv->private_buffer_rect.x1 = x0; 157035c4bbdfSmrg pDRIPriv->private_buffer_rect.y1 = y0; 157135c4bbdfSmrg pDRIPriv->private_buffer_rect.x2 = x1; 157235c4bbdfSmrg pDRIPriv->private_buffer_rect.y2 = y1; 157335c4bbdfSmrg 157435c4bbdfSmrg *numBackClipRects = 1; 157535c4bbdfSmrg *pBackClipRects = &(pDRIPriv->private_buffer_rect); 157635c4bbdfSmrg } 157735c4bbdfSmrg } 157835c4bbdfSmrg else { 157935c4bbdfSmrg /* Use the frontbuffer cliprects for back buffers. */ 158035c4bbdfSmrg *numBackClipRects = 0; 158135c4bbdfSmrg *pBackClipRects = 0; 158235c4bbdfSmrg } 158335c4bbdfSmrg } 158435c4bbdfSmrg else { 158535c4bbdfSmrg /* Not a DRIDrawable */ 158635c4bbdfSmrg return FALSE; 158735c4bbdfSmrg } 158835c4bbdfSmrg } 158935c4bbdfSmrg else { /* pixmap (or for GLX 1.3, a PBuffer) */ 159035c4bbdfSmrg /* NOT_DONE */ 159135c4bbdfSmrg return FALSE; 159205b261ecSmrg } 159305b261ecSmrg 159405b261ecSmrg return TRUE; 159505b261ecSmrg} 159605b261ecSmrg 159705b261ecSmrgBool 159805b261ecSmrgDRIGetDeviceInfo(ScreenPtr pScreen, 159905b261ecSmrg drm_handle_t * hFrameBuffer, 160035c4bbdfSmrg int *fbOrigin, 160135c4bbdfSmrg int *fbSize, 160235c4bbdfSmrg int *fbStride, int *devPrivateSize, void **pDevPrivate) 160305b261ecSmrg{ 160405b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 160505b261ecSmrg 160605b261ecSmrg *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer; 160705b261ecSmrg *fbOrigin = 0; 160805b261ecSmrg *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; 160905b261ecSmrg *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; 161005b261ecSmrg *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; 161105b261ecSmrg *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; 161205b261ecSmrg 161305b261ecSmrg return TRUE; 161405b261ecSmrg} 161505b261ecSmrg 161605b261ecSmrgDRIInfoPtr 161705b261ecSmrgDRICreateInfoRec(void) 161805b261ecSmrg{ 161935c4bbdfSmrg DRIInfoPtr inforec = (DRIInfoPtr) calloc(1, sizeof(DRIInfoRec)); 162035c4bbdfSmrg 162135c4bbdfSmrg if (!inforec) 162235c4bbdfSmrg return NULL; 162305b261ecSmrg 162405b261ecSmrg /* Initialize defaults */ 162505b261ecSmrg inforec->busIdString = NULL; 162605b261ecSmrg 162705b261ecSmrg /* Wrapped function defaults */ 162835c4bbdfSmrg inforec->wrap.WakeupHandler = DRIDoWakeupHandler; 162935c4bbdfSmrg inforec->wrap.BlockHandler = DRIDoBlockHandler; 163035c4bbdfSmrg inforec->wrap.WindowExposures = DRIWindowExposures; 163135c4bbdfSmrg inforec->wrap.CopyWindow = DRICopyWindow; 163235c4bbdfSmrg inforec->wrap.ClipNotify = DRIClipNotify; 163335c4bbdfSmrg inforec->wrap.AdjustFrame = DRIAdjustFrame; 163405b261ecSmrg 163505b261ecSmrg inforec->TransitionTo2d = 0; 163605b261ecSmrg inforec->TransitionTo3d = 0; 163705b261ecSmrg inforec->SetDrawableIndex = 0; 163805b261ecSmrg 163905b261ecSmrg return inforec; 164005b261ecSmrg} 164105b261ecSmrg 164205b261ecSmrgvoid 164305b261ecSmrgDRIDestroyInfoRec(DRIInfoPtr DRIInfo) 164405b261ecSmrg{ 16456747b715Smrg free(DRIInfo->busIdString); 164635c4bbdfSmrg free((char *) DRIInfo); 164705b261ecSmrg} 164805b261ecSmrg 164905b261ecSmrgvoid 16501b5d61b8SmrgDRIWakeupHandler(void *wakeupData, int result) 165105b261ecSmrg{ 165205b261ecSmrg int i; 165305b261ecSmrg 165405b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) { 165535c4bbdfSmrg ScreenPtr pScreen = screenInfo.screens[i]; 165635c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 165705b261ecSmrg 165835c4bbdfSmrg if (pDRIPriv && pDRIPriv->pDriverInfo->wrap.WakeupHandler) 16591b5d61b8Smrg (*pDRIPriv->pDriverInfo->wrap.WakeupHandler) (pScreen, result); 166005b261ecSmrg } 166105b261ecSmrg} 166205b261ecSmrg 166305b261ecSmrgvoid 16641b5d61b8SmrgDRIBlockHandler(void *blockData, void *pTimeout) 166505b261ecSmrg{ 166605b261ecSmrg int i; 166705b261ecSmrg 166805b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) { 166935c4bbdfSmrg ScreenPtr pScreen = screenInfo.screens[i]; 167035c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 167105b261ecSmrg 167235c4bbdfSmrg if (pDRIPriv && pDRIPriv->pDriverInfo->wrap.BlockHandler) 16731b5d61b8Smrg (*pDRIPriv->pDriverInfo->wrap.BlockHandler) (pScreen, pTimeout); 167405b261ecSmrg } 167505b261ecSmrg} 167605b261ecSmrg 167705b261ecSmrgvoid 16781b5d61b8SmrgDRIDoWakeupHandler(ScreenPtr pScreen, int result) 167905b261ecSmrg{ 168005b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 168105b261ecSmrg 168205b261ecSmrg DRILock(pScreen, 0); 168305b261ecSmrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 168435c4bbdfSmrg /* hide X context by swapping 2D component here */ 168535c4bbdfSmrg (*pDRIPriv->pDriverInfo->SwapContext) (pScreen, 168635c4bbdfSmrg DRI_3D_SYNC, 168735c4bbdfSmrg DRI_2D_CONTEXT, 168835c4bbdfSmrg pDRIPriv->partial3DContextStore, 168935c4bbdfSmrg DRI_2D_CONTEXT, 169035c4bbdfSmrg pDRIPriv->hiddenContextStore); 169105b261ecSmrg } 169205b261ecSmrg} 169305b261ecSmrg 169405b261ecSmrgvoid 16951b5d61b8SmrgDRIDoBlockHandler(ScreenPtr pScreen, void *timeout) 169605b261ecSmrg{ 169705b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 169805b261ecSmrg 169905b261ecSmrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 170035c4bbdfSmrg /* hide X context by swapping 2D component here */ 170135c4bbdfSmrg (*pDRIPriv->pDriverInfo->SwapContext) (pScreen, 170235c4bbdfSmrg DRI_2D_SYNC, 170335c4bbdfSmrg DRI_NO_CONTEXT, 170435c4bbdfSmrg NULL, 170535c4bbdfSmrg DRI_2D_CONTEXT, 170635c4bbdfSmrg pDRIPriv->partial3DContextStore); 170705b261ecSmrg } 170805b261ecSmrg 170905b261ecSmrg if (pDRIPriv->windowsTouched) 171005b261ecSmrg DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); 171105b261ecSmrg pDRIPriv->windowsTouched = FALSE; 171205b261ecSmrg 171305b261ecSmrg DRIUnlock(pScreen); 171405b261ecSmrg} 171505b261ecSmrg 171605b261ecSmrgvoid 171705b261ecSmrgDRISwapContext(int drmFD, void *oldctx, void *newctx) 171805b261ecSmrg{ 171935c4bbdfSmrg DRIContextPrivPtr oldContext = (DRIContextPrivPtr) oldctx; 172035c4bbdfSmrg DRIContextPrivPtr newContext = (DRIContextPrivPtr) newctx; 172135c4bbdfSmrg ScreenPtr pScreen = newContext->pScreen; 172235c4bbdfSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 172335c4bbdfSmrg void *oldContextStore = NULL; 172435c4bbdfSmrg DRIContextType oldContextType; 172535c4bbdfSmrg void *newContextStore = NULL; 172635c4bbdfSmrg DRIContextType newContextType; 172735c4bbdfSmrg DRISyncType syncType; 172835c4bbdfSmrg 172905b261ecSmrg#ifdef DEBUG 173035c4bbdfSmrg static int count = 0; 173105b261ecSmrg 173205b261ecSmrg if (!newContext) { 173335c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 173435c4bbdfSmrg "[DRI] Context Switch Error: oldContext=%p, newContext=%p\n", 173535c4bbdfSmrg oldContext, newContext); 173635c4bbdfSmrg return; 173705b261ecSmrg } 173805b261ecSmrg 1739ed6184dfSmrg /* useful for debugging, just print out after n context switches */ 174005b261ecSmrg if (!count || !(count % 1)) { 174135c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 174235c4bbdfSmrg "[DRI] Context switch %5d from %p/0x%08x (%d)\n", 174335c4bbdfSmrg count, 174435c4bbdfSmrg oldContext, 174535c4bbdfSmrg oldContext ? oldContext->flags : 0, 174635c4bbdfSmrg oldContext ? oldContext->hwContext : -1); 174735c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_INFO, 174835c4bbdfSmrg "[DRI] Context switch %5d to %p/0x%08x (%d)\n", 174935c4bbdfSmrg count, 175035c4bbdfSmrg newContext, 175135c4bbdfSmrg newContext ? newContext->flags : 0, 175235c4bbdfSmrg newContext ? newContext->hwContext : -1); 175305b261ecSmrg } 175405b261ecSmrg ++count; 175505b261ecSmrg#endif 175605b261ecSmrg 175705b261ecSmrg if (!pDRIPriv->pDriverInfo->SwapContext) { 175835c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 175935c4bbdfSmrg "[DRI] DDX driver missing context swap call back\n"); 176035c4bbdfSmrg return; 176105b261ecSmrg } 176205b261ecSmrg 176305b261ecSmrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 176405b261ecSmrg 176505b261ecSmrg /* only 3D contexts are swapped in this case */ 176635c4bbdfSmrg if (oldContext) { 176735c4bbdfSmrg oldContextStore = DRIGetContextStore(oldContext); 176835c4bbdfSmrg oldContext->valid3D = TRUE; 176935c4bbdfSmrg oldContextType = DRI_3D_CONTEXT; 177035c4bbdfSmrg } 177135c4bbdfSmrg else { 177235c4bbdfSmrg oldContextType = DRI_NO_CONTEXT; 177335c4bbdfSmrg } 177435c4bbdfSmrg newContextStore = DRIGetContextStore(newContext); 177535c4bbdfSmrg if ((newContext->valid3D) && 177635c4bbdfSmrg (newContext->hwContext != pDRIPriv->myContext)) { 177735c4bbdfSmrg newContextType = DRI_3D_CONTEXT; 177835c4bbdfSmrg } 177935c4bbdfSmrg else { 178035c4bbdfSmrg newContextType = DRI_2D_CONTEXT; 178135c4bbdfSmrg } 178235c4bbdfSmrg syncType = DRI_3D_SYNC; 178335c4bbdfSmrg } 178435c4bbdfSmrg else { /* default: driverSwapMethod == DRI_SERVER_SWAP */ 178505b261ecSmrg 178605b261ecSmrg /* optimize 2D context swaps */ 178705b261ecSmrg 178835c4bbdfSmrg if (newContext->flags & DRI_CONTEXT_2DONLY) { 178935c4bbdfSmrg /* go from 3D context to 2D context and only save 2D 179005b261ecSmrg * subset of 3D state 179105b261ecSmrg */ 179235c4bbdfSmrg oldContextStore = DRIGetContextStore(oldContext); 179335c4bbdfSmrg oldContextType = DRI_2D_CONTEXT; 179435c4bbdfSmrg newContextStore = DRIGetContextStore(newContext); 179535c4bbdfSmrg newContextType = DRI_2D_CONTEXT; 179635c4bbdfSmrg syncType = DRI_3D_SYNC; 179735c4bbdfSmrg pDRIPriv->lastPartial3DContext = oldContext; 179835c4bbdfSmrg } 179935c4bbdfSmrg else if (oldContext->flags & DRI_CONTEXT_2DONLY) { 180035c4bbdfSmrg if (pDRIPriv->lastPartial3DContext == newContext) { 180135c4bbdfSmrg /* go from 2D context back to previous 3D context and 180235c4bbdfSmrg * only restore 2D subset of previous 3D state 180335c4bbdfSmrg */ 180435c4bbdfSmrg oldContextStore = DRIGetContextStore(oldContext); 180535c4bbdfSmrg oldContextType = DRI_2D_CONTEXT; 180635c4bbdfSmrg newContextStore = DRIGetContextStore(newContext); 180735c4bbdfSmrg newContextType = DRI_2D_CONTEXT; 180835c4bbdfSmrg syncType = DRI_2D_SYNC; 180935c4bbdfSmrg } 181035c4bbdfSmrg else { 181135c4bbdfSmrg /* go from 2D context to a different 3D context */ 181235c4bbdfSmrg 181335c4bbdfSmrg /* call DDX driver to do partial restore */ 181435c4bbdfSmrg oldContextStore = DRIGetContextStore(oldContext); 181535c4bbdfSmrg newContextStore = 181635c4bbdfSmrg DRIGetContextStore(pDRIPriv->lastPartial3DContext); 181735c4bbdfSmrg (*pDRIPriv->pDriverInfo->SwapContext) (pScreen, 181835c4bbdfSmrg DRI_2D_SYNC, 181935c4bbdfSmrg DRI_2D_CONTEXT, 182035c4bbdfSmrg oldContextStore, 182135c4bbdfSmrg DRI_2D_CONTEXT, 182235c4bbdfSmrg newContextStore); 182335c4bbdfSmrg 182435c4bbdfSmrg /* now setup for a complete 3D swap */ 182535c4bbdfSmrg oldContextStore = newContextStore; 182635c4bbdfSmrg oldContext->valid3D = TRUE; 182735c4bbdfSmrg oldContextType = DRI_3D_CONTEXT; 182835c4bbdfSmrg newContextStore = DRIGetContextStore(newContext); 182935c4bbdfSmrg if ((newContext->valid3D) && 183035c4bbdfSmrg (newContext->hwContext != pDRIPriv->myContext)) { 183135c4bbdfSmrg newContextType = DRI_3D_CONTEXT; 183235c4bbdfSmrg } 183335c4bbdfSmrg else { 183435c4bbdfSmrg newContextType = DRI_2D_CONTEXT; 183535c4bbdfSmrg } 183635c4bbdfSmrg syncType = DRI_NO_SYNC; 183735c4bbdfSmrg } 183835c4bbdfSmrg } 183935c4bbdfSmrg else { 184035c4bbdfSmrg /* now setup for a complete 3D swap */ 184135c4bbdfSmrg oldContextStore = newContextStore; 184235c4bbdfSmrg oldContext->valid3D = TRUE; 184335c4bbdfSmrg oldContextType = DRI_3D_CONTEXT; 184435c4bbdfSmrg newContextStore = DRIGetContextStore(newContext); 184535c4bbdfSmrg if ((newContext->valid3D) && 184635c4bbdfSmrg (newContext->hwContext != pDRIPriv->myContext)) { 184735c4bbdfSmrg newContextType = DRI_3D_CONTEXT; 184835c4bbdfSmrg } 184935c4bbdfSmrg else { 185035c4bbdfSmrg newContextType = DRI_2D_CONTEXT; 185135c4bbdfSmrg } 185235c4bbdfSmrg syncType = DRI_3D_SYNC; 185335c4bbdfSmrg } 185405b261ecSmrg } 185505b261ecSmrg 185605b261ecSmrg /* call DDX driver to perform the swap */ 185735c4bbdfSmrg (*pDRIPriv->pDriverInfo->SwapContext) (pScreen, 185835c4bbdfSmrg syncType, 185935c4bbdfSmrg oldContextType, 186035c4bbdfSmrg oldContextStore, 186135c4bbdfSmrg newContextType, newContextStore); 186205b261ecSmrg} 186305b261ecSmrg 186435c4bbdfSmrgvoid * 186505b261ecSmrgDRIGetContextStore(DRIContextPrivPtr context) 186605b261ecSmrg{ 186735c4bbdfSmrg return ((void *) context->pContextStore); 186805b261ecSmrg} 186905b261ecSmrg 187005b261ecSmrgvoid 187135c4bbdfSmrgDRIWindowExposures(WindowPtr pWin, RegionPtr prgn) 187205b261ecSmrg{ 187305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 187405b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 187505b261ecSmrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 187605b261ecSmrg 187735c4bbdfSmrg if (pDRIDrawablePriv) { 187835c4bbdfSmrg (*pDRIPriv->pDriverInfo->InitBuffers) (pWin, prgn, 187905b261ecSmrg pDRIDrawablePriv->drawableIndex); 188005b261ecSmrg } 188105b261ecSmrg 188205b261ecSmrg /* call lower wrapped functions */ 188305b261ecSmrg if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { 188405b261ecSmrg 188535c4bbdfSmrg /* unwrap */ 188635c4bbdfSmrg pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 188705b261ecSmrg 188835c4bbdfSmrg /* call lower layers */ 188935c4bbdfSmrg (*pScreen->WindowExposures) (pWin, prgn); 189005b261ecSmrg 189135c4bbdfSmrg /* rewrap */ 189235c4bbdfSmrg pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 189335c4bbdfSmrg pScreen->WindowExposures = DRIWindowExposures; 189405b261ecSmrg } 189505b261ecSmrg} 189605b261ecSmrg 189705b261ecSmrgstatic int 189835c4bbdfSmrgDRITreeTraversal(WindowPtr pWin, void *data) 189905b261ecSmrg{ 190005b261ecSmrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 190105b261ecSmrg 190235c4bbdfSmrg if (pDRIDrawablePriv) { 190305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 190405b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 190505b261ecSmrg 190635c4bbdfSmrg if (RegionNumRects(&(pWin->clipList)) > 0) { 190735c4bbdfSmrg RegionPtr reg = (RegionPtr) data; 190805b261ecSmrg 190935c4bbdfSmrg RegionUnion(reg, reg, &(pWin->clipList)); 191035c4bbdfSmrg pDRIPriv->nrWalked++; 191135c4bbdfSmrg } 191205b261ecSmrg 191335c4bbdfSmrg if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) 191435c4bbdfSmrg return WT_STOPWALKING; 191505b261ecSmrg } 191605b261ecSmrg return WT_WALKCHILDREN; 191705b261ecSmrg} 191805b261ecSmrg 191905b261ecSmrgBool 192005b261ecSmrgDRIDestroyWindow(WindowPtr pWin) 192105b261ecSmrg{ 192205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 192305b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 192405b261ecSmrg Bool retval = TRUE; 192505b261ecSmrg 192605b261ecSmrg DRIDrawablePrivDestroy(pWin); 192705b261ecSmrg 192805b261ecSmrg /* call lower wrapped functions */ 192935c4bbdfSmrg if (pDRIPriv->DestroyWindow) { 193035c4bbdfSmrg /* unwrap */ 193135c4bbdfSmrg pScreen->DestroyWindow = pDRIPriv->DestroyWindow; 193205b261ecSmrg 193335c4bbdfSmrg /* call lower layers */ 193435c4bbdfSmrg retval = (*pScreen->DestroyWindow) (pWin); 193505b261ecSmrg 193635c4bbdfSmrg /* rewrap */ 193735c4bbdfSmrg pDRIPriv->DestroyWindow = pScreen->DestroyWindow; 193835c4bbdfSmrg pScreen->DestroyWindow = DRIDestroyWindow; 193905b261ecSmrg } 194005b261ecSmrg 194105b261ecSmrg return retval; 194205b261ecSmrg} 194305b261ecSmrg 194405b261ecSmrgvoid 194505b261ecSmrgDRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 194605b261ecSmrg{ 194705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 194805b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 194905b261ecSmrg 195035c4bbdfSmrg if (!pDRIPriv) 195135c4bbdfSmrg return; 195205b261ecSmrg 195335c4bbdfSmrg if (pDRIPriv->nrWindowsVisible > 0) { 195435c4bbdfSmrg RegionRec reg; 195505b261ecSmrg 195635c4bbdfSmrg RegionNull(®); 195735c4bbdfSmrg pDRIPriv->nrWalked = 0; 195835c4bbdfSmrg TraverseTree(pWin, DRITreeTraversal, (void *) (®)); 195905b261ecSmrg 196035c4bbdfSmrg if (RegionNotEmpty(®)) { 196135c4bbdfSmrg RegionTranslate(®, ptOldOrg.x - pWin->drawable.x, 196235c4bbdfSmrg ptOldOrg.y - pWin->drawable.y); 196335c4bbdfSmrg RegionIntersect(®, ®, prgnSrc); 196405b261ecSmrg 196535c4bbdfSmrg /* The MoveBuffers interface is not ideal */ 196635c4bbdfSmrg (*pDRIPriv->pDriverInfo->MoveBuffers) (pWin, ptOldOrg, ®, 196735c4bbdfSmrg pDRIPriv->pDriverInfo-> 196835c4bbdfSmrg ddxDrawableTableEntry); 196935c4bbdfSmrg } 197005b261ecSmrg 197135c4bbdfSmrg RegionUninit(®); 197205b261ecSmrg } 197305b261ecSmrg 197405b261ecSmrg /* call lower wrapped functions */ 197535c4bbdfSmrg if (pDRIPriv->wrap.CopyWindow) { 197635c4bbdfSmrg /* unwrap */ 197735c4bbdfSmrg pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 197805b261ecSmrg 197935c4bbdfSmrg /* call lower layers */ 198035c4bbdfSmrg (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); 198105b261ecSmrg 198235c4bbdfSmrg /* rewrap */ 198335c4bbdfSmrg pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 198435c4bbdfSmrg pScreen->CopyWindow = DRICopyWindow; 198505b261ecSmrg } 198605b261ecSmrg} 198705b261ecSmrg 198805b261ecSmrgstatic void 198905b261ecSmrgDRIGetSecs(long *secs, long *usecs) 199005b261ecSmrg{ 199105b261ecSmrg struct timeval tv; 199205b261ecSmrg 199305b261ecSmrg gettimeofday(&tv, NULL); 199405b261ecSmrg 199535c4bbdfSmrg *secs = tv.tv_sec; 199605b261ecSmrg *usecs = tv.tv_usec; 199705b261ecSmrg} 199805b261ecSmrg 199905b261ecSmrgstatic unsigned long 200005b261ecSmrgDRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, 200135c4bbdfSmrg unsigned long f_secs, unsigned long f_usecs) 200205b261ecSmrg{ 200305b261ecSmrg if (f_usecs < s_usecs) { 200435c4bbdfSmrg --f_secs; 200535c4bbdfSmrg f_usecs += 1000000; 200605b261ecSmrg } 200705b261ecSmrg return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; 200805b261ecSmrg} 200905b261ecSmrg 201005b261ecSmrgstatic void 201135c4bbdfSmrgDRISpinLockTimeout(drmLock * lock, int val, unsigned long timeout /* in mS */ ) 201205b261ecSmrg{ 201335c4bbdfSmrg int count = 10000; 201435c4bbdfSmrg 201505b261ecSmrg#if !defined(__alpha__) && !defined(__powerpc__) 201605b261ecSmrg char ret; 201705b261ecSmrg#else 201805b261ecSmrg int ret; 201905b261ecSmrg#endif 202005b261ecSmrg long s_secs, s_usecs; 202105b261ecSmrg long f_secs, f_usecs; 202205b261ecSmrg long msecs; 202335c4bbdfSmrg long prev = 0; 202405b261ecSmrg 202505b261ecSmrg DRIGetSecs(&s_secs, &s_usecs); 202605b261ecSmrg 202705b261ecSmrg do { 202835c4bbdfSmrg DRM_SPINLOCK_COUNT(lock, val, count, ret); 202935c4bbdfSmrg if (!ret) 203035c4bbdfSmrg return; /* Got lock */ 203135c4bbdfSmrg DRIGetSecs(&f_secs, &f_usecs); 203235c4bbdfSmrg msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); 203335c4bbdfSmrg if (msecs - prev < 250) 203435c4bbdfSmrg count *= 2; /* Not more than 0.5S */ 203505b261ecSmrg } while (msecs < timeout); 203605b261ecSmrg 203735c4bbdfSmrg /* Didn't get lock, so take it. The worst 203835c4bbdfSmrg that can happen is that there is some 203935c4bbdfSmrg garbage written to the wrong part of the 204035c4bbdfSmrg framebuffer that a refresh will repair. 204135c4bbdfSmrg That's undesirable, but better than 204235c4bbdfSmrg locking the server. This should be a 204335c4bbdfSmrg very rare event. */ 204405b261ecSmrg DRM_SPINLOCK_TAKE(lock, val); 204505b261ecSmrg} 204605b261ecSmrg 204705b261ecSmrgstatic void 204805b261ecSmrgDRILockTree(ScreenPtr pScreen) 204905b261ecSmrg{ 205005b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 205105b261ecSmrg 205235c4bbdfSmrg if (!pDRIPriv) 205335c4bbdfSmrg return; 205405b261ecSmrg 205505b261ecSmrg /* Restore the last known 3D context if the X context is hidden */ 205605b261ecSmrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 205735c4bbdfSmrg (*pDRIPriv->pDriverInfo->SwapContext) (pScreen, 205835c4bbdfSmrg DRI_2D_SYNC, 205935c4bbdfSmrg DRI_NO_CONTEXT, 206035c4bbdfSmrg NULL, 206135c4bbdfSmrg DRI_2D_CONTEXT, 206235c4bbdfSmrg pDRIPriv->partial3DContextStore); 206305b261ecSmrg } 206405b261ecSmrg 206505b261ecSmrg /* Call kernel to release lock */ 206605b261ecSmrg DRIUnlock(pScreen); 206705b261ecSmrg 206805b261ecSmrg /* Grab drawable spin lock: a time out between 10 and 30 seconds is 206905b261ecSmrg appropriate, since this should never time out except in the case of 207005b261ecSmrg client death while the lock is being held. The timeout must be 207105b261ecSmrg greater than any reasonable rendering time. */ 207235c4bbdfSmrg DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs */ 207305b261ecSmrg 207405b261ecSmrg /* Call kernel flush outstanding buffers and relock */ 207535c4bbdfSmrg DRILock(pScreen, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH_ALL); 207605b261ecSmrg 207705b261ecSmrg /* Switch back to our 2D context if the X context is hidden */ 207805b261ecSmrg if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 207935c4bbdfSmrg /* hide X context by swapping 2D component here */ 208035c4bbdfSmrg (*pDRIPriv->pDriverInfo->SwapContext) (pScreen, 208135c4bbdfSmrg DRI_3D_SYNC, 208235c4bbdfSmrg DRI_2D_CONTEXT, 208335c4bbdfSmrg pDRIPriv->partial3DContextStore, 208435c4bbdfSmrg DRI_2D_CONTEXT, 208535c4bbdfSmrg pDRIPriv->hiddenContextStore); 208605b261ecSmrg } 208705b261ecSmrg} 208805b261ecSmrg 208905b261ecSmrgvoid 209005b261ecSmrgDRIClipNotify(WindowPtr pWin, int dx, int dy) 209105b261ecSmrg{ 209205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 209305b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 209435c4bbdfSmrg DRIDrawablePrivPtr pDRIDrawablePriv; 209505b261ecSmrg 209635c4bbdfSmrg if (!pDRIPriv) 209735c4bbdfSmrg return; 209805b261ecSmrg 209905b261ecSmrg if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 21006747b715Smrg int nrects = RegionNumRects(&pWin->clipList); 210105b261ecSmrg 210235c4bbdfSmrg if (!pDRIPriv->windowsTouched) { 210305b261ecSmrg DRILockTree(pScreen); 210405b261ecSmrg pDRIPriv->windowsTouched = TRUE; 210505b261ecSmrg } 210605b261ecSmrg 210735c4bbdfSmrg if (nrects && !pDRIDrawablePriv->nrects) 210835c4bbdfSmrg DRIIncreaseNumberVisible(pScreen); 210935c4bbdfSmrg else if (!nrects && pDRIDrawablePriv->nrects) 211035c4bbdfSmrg DRIDecreaseNumberVisible(pScreen); 211135c4bbdfSmrg else 211235c4bbdfSmrg DRIDriverClipNotify(pScreen); 211305b261ecSmrg 211435c4bbdfSmrg pDRIDrawablePriv->nrects = nrects; 211505b261ecSmrg 211635c4bbdfSmrg pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp 211735c4bbdfSmrg = DRIDrawableValidationStamp++; 211805b261ecSmrg 211935c4bbdfSmrg drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable, 212035c4bbdfSmrg DRM_DRAWABLE_CLIPRECTS, 212135c4bbdfSmrg nrects, RegionRects(&pWin->clipList)); 212205b261ecSmrg } 212305b261ecSmrg 212405b261ecSmrg /* call lower wrapped functions */ 212535c4bbdfSmrg if (pDRIPriv->wrap.ClipNotify) { 212605b261ecSmrg 212735c4bbdfSmrg /* unwrap */ 212805b261ecSmrg pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 212905b261ecSmrg 213035c4bbdfSmrg /* call lower layers */ 213135c4bbdfSmrg (*pScreen->ClipNotify) (pWin, dx, dy); 213205b261ecSmrg 213335c4bbdfSmrg /* rewrap */ 213405b261ecSmrg pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 213505b261ecSmrg pScreen->ClipNotify = DRIClipNotify; 213605b261ecSmrg } 213705b261ecSmrg} 213805b261ecSmrg 213905b261ecSmrgCARD32 214005b261ecSmrgDRIGetDrawableIndex(WindowPtr pWin) 214105b261ecSmrg{ 214205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 214305b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 214405b261ecSmrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 214505b261ecSmrg CARD32 index; 214605b261ecSmrg 214705b261ecSmrg if (pDRIDrawablePriv) { 214835c4bbdfSmrg index = pDRIDrawablePriv->drawableIndex; 214905b261ecSmrg } 215005b261ecSmrg else { 215135c4bbdfSmrg index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; 215205b261ecSmrg } 215305b261ecSmrg 215405b261ecSmrg return index; 215505b261ecSmrg} 215605b261ecSmrg 215705b261ecSmrgunsigned int 215805b261ecSmrgDRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) 215905b261ecSmrg{ 216005b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 216135c4bbdfSmrg 216205b261ecSmrg return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; 216305b261ecSmrg} 216405b261ecSmrg 216505b261ecSmrgvoid 216605b261ecSmrgDRIPrintDrawableLock(ScreenPtr pScreen, char *msg) 216705b261ecSmrg{ 216805b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 216905b261ecSmrg 217035c4bbdfSmrg ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); 217105b261ecSmrg} 217205b261ecSmrg 217305b261ecSmrgvoid 217405b261ecSmrgDRILock(ScreenPtr pScreen, int flags) 217505b261ecSmrg{ 217605b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 217705b261ecSmrg 217835c4bbdfSmrg if (!pDRIPriv || !pDRIPriv->pLockRefCount) 217935c4bbdfSmrg return; 218005b261ecSmrg 218105b261ecSmrg if (!*pDRIPriv->pLockRefCount) { 218235c4bbdfSmrg DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, 218335c4bbdfSmrg flags); 218435c4bbdfSmrg *pDRIPriv->pLockingContext = pDRIPriv->myContext; 218535c4bbdfSmrg } 218635c4bbdfSmrg else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) { 218735c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 218835c4bbdfSmrg "[DRI] Locking deadlock.\n" 218935c4bbdfSmrg "\tAlready locked with context %p,\n" 219035c4bbdfSmrg "\ttrying to lock with context %p.\n", 219135c4bbdfSmrg pDRIPriv->pLockingContext, (void *) (uintptr_t) pDRIPriv->myContext); 219205b261ecSmrg } 219305b261ecSmrg (*pDRIPriv->pLockRefCount)++; 219405b261ecSmrg} 219505b261ecSmrg 219605b261ecSmrgvoid 219705b261ecSmrgDRIUnlock(ScreenPtr pScreen) 219805b261ecSmrg{ 219905b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 220005b261ecSmrg 220135c4bbdfSmrg if (!pDRIPriv || !pDRIPriv->pLockRefCount) 220235c4bbdfSmrg return; 220305b261ecSmrg 220405b261ecSmrg if (*pDRIPriv->pLockRefCount > 0) { 220535c4bbdfSmrg if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) { 220635c4bbdfSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 220735c4bbdfSmrg "[DRI] Unlocking inconsistency:\n" 220835c4bbdfSmrg "\tContext %p trying to unlock lock held by context %p\n", 220935c4bbdfSmrg pDRIPriv->pLockingContext, (void *) (uintptr_t) pDRIPriv->myContext); 221035c4bbdfSmrg } 221135c4bbdfSmrg (*pDRIPriv->pLockRefCount)--; 221235c4bbdfSmrg } 221335c4bbdfSmrg else { 221405b261ecSmrg DRIDrvMsg(pScreen->myNum, X_ERROR, 221535c4bbdfSmrg "DRIUnlock called when not locked.\n"); 221605b261ecSmrg return; 221705b261ecSmrg } 221835c4bbdfSmrg if (!*pDRIPriv->pLockRefCount) 221905b261ecSmrg DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext); 222005b261ecSmrg} 222105b261ecSmrg 222205b261ecSmrgvoid * 222305b261ecSmrgDRIGetSAREAPrivate(ScreenPtr pScreen) 222405b261ecSmrg{ 222505b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 222605b261ecSmrg 222735c4bbdfSmrg if (!pDRIPriv) 222835c4bbdfSmrg return 0; 222935c4bbdfSmrg 223035c4bbdfSmrg return (void *) (((char *) pDRIPriv->pSAREA) + sizeof(XF86DRISAREARec)); 223105b261ecSmrg} 223205b261ecSmrg 223305b261ecSmrgdrm_context_t 223405b261ecSmrgDRIGetContext(ScreenPtr pScreen) 223505b261ecSmrg{ 223605b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 223735c4bbdfSmrg 223835c4bbdfSmrg if (!pDRIPriv) 223935c4bbdfSmrg return 0; 224005b261ecSmrg 224105b261ecSmrg return pDRIPriv->myContext; 224205b261ecSmrg} 224305b261ecSmrg 224405b261ecSmrgvoid 224505b261ecSmrgDRIGetTexOffsetFuncs(ScreenPtr pScreen, 224635c4bbdfSmrg DRITexOffsetStartProcPtr * texOffsetStartFunc, 224735c4bbdfSmrg DRITexOffsetFinishProcPtr * texOffsetFinishFunc) 224805b261ecSmrg{ 224905b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 225005b261ecSmrg 225135c4bbdfSmrg if (!pDRIPriv) 225235c4bbdfSmrg return; 225305b261ecSmrg 225435c4bbdfSmrg *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart; 225505b261ecSmrg *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish; 225605b261ecSmrg} 225705b261ecSmrg 225805b261ecSmrg/* This lets get at the unwrapped functions so that they can correctly 225905b261ecSmrg * call the lowerlevel functions, and choose whether they will be 226005b261ecSmrg * called at every level of recursion (eg in validatetree). 226105b261ecSmrg */ 226205b261ecSmrgDRIWrappedFuncsRec * 226305b261ecSmrgDRIGetWrappedFuncs(ScreenPtr pScreen) 226405b261ecSmrg{ 226505b261ecSmrg return &(DRI_SCREEN_PRIV(pScreen)->wrap); 226605b261ecSmrg} 226705b261ecSmrg 226805b261ecSmrg/* note that this returns the library version, not the protocol version */ 226905b261ecSmrgvoid 227035c4bbdfSmrgDRIQueryVersion(int *majorVersion, int *minorVersion, int *patchVersion) 227105b261ecSmrg{ 227205b261ecSmrg *majorVersion = DRIINFO_MAJOR_VERSION; 227305b261ecSmrg *minorVersion = DRIINFO_MINOR_VERSION; 227405b261ecSmrg *patchVersion = DRIINFO_PATCH_VERSION; 227505b261ecSmrg} 227605b261ecSmrg 227705b261ecSmrgstatic void 227805b261ecSmrg_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) 227905b261ecSmrg{ 228035c4bbdfSmrg pDRIPriv->pSAREA->frame.x = x; 228135c4bbdfSmrg pDRIPriv->pSAREA->frame.y = y; 228235c4bbdfSmrg pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; 228305b261ecSmrg pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; 228405b261ecSmrg} 228505b261ecSmrg 228605b261ecSmrgvoid 228735c4bbdfSmrgDRIAdjustFrame(ScrnInfoPtr pScrn, int x, int y) 228805b261ecSmrg{ 228935c4bbdfSmrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 229005b261ecSmrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 229135c4bbdfSmrg int px, py; 229205b261ecSmrg 229305b261ecSmrg if (!pDRIPriv || !pDRIPriv->pSAREA) { 229435c4bbdfSmrg DRIDrvMsg(pScrn->scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", 229535c4bbdfSmrg pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); 229635c4bbdfSmrg return; 229705b261ecSmrg } 229805b261ecSmrg 229905b261ecSmrg if (pDRIPriv->fullscreen) { 230035c4bbdfSmrg /* Fix up frame */ 230135c4bbdfSmrg pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; 230235c4bbdfSmrg pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; 230335c4bbdfSmrg pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; 230435c4bbdfSmrg pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; 230535c4bbdfSmrg 230635c4bbdfSmrg /* Fix up cursor */ 230735c4bbdfSmrg miPointerGetPosition(inputInfo.pointer, &px, &py); 230835c4bbdfSmrg 230935c4bbdfSmrg if (px < pScrn->frameX0) 231035c4bbdfSmrg px = pScrn->frameX0; 231135c4bbdfSmrg if (px > pScrn->frameX1) 231235c4bbdfSmrg px = pScrn->frameX1; 231335c4bbdfSmrg if (py < pScrn->frameY0) 231435c4bbdfSmrg py = pScrn->frameY0; 231535c4bbdfSmrg if (py > pScrn->frameY1) 231635c4bbdfSmrg py = pScrn->frameY1; 231735c4bbdfSmrg pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE); 231835c4bbdfSmrg 231935c4bbdfSmrg return; 232005b261ecSmrg } 232105b261ecSmrg 232205b261ecSmrg if (pDRIPriv->wrap.AdjustFrame) { 232335c4bbdfSmrg /* unwrap */ 232435c4bbdfSmrg pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; 232535c4bbdfSmrg /* call lower layers */ 232635c4bbdfSmrg (*pScrn->AdjustFrame) (pScrn, x, y); 232735c4bbdfSmrg /* rewrap */ 232835c4bbdfSmrg pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; 232935c4bbdfSmrg pScrn->AdjustFrame = DRIAdjustFrame; 233005b261ecSmrg } 233105b261ecSmrg 233205b261ecSmrg _DRIAdjustFrame(pScrn, pDRIPriv, x, y); 233305b261ecSmrg} 233405b261ecSmrg 233535c4bbdfSmrg/* 233605b261ecSmrg * DRIMoveBuffersHelper swaps the regions rects in place leaving you 233705b261ecSmrg * a region with the rects in the order that you need to blit them, 233805b261ecSmrg * but it is possibly (likely) an invalid region afterwards. If you 233935c4bbdfSmrg * need to use the region again for anything you have to call 234005b261ecSmrg * REGION_VALIDATE on it, or better yet, save a copy first. 234105b261ecSmrg */ 234205b261ecSmrg 234305b261ecSmrgvoid 234435c4bbdfSmrgDRIMoveBuffersHelper(ScreenPtr pScreen, 234535c4bbdfSmrg int dx, int dy, int *xdir, int *ydir, RegionPtr reg) 234635c4bbdfSmrg{ 234735c4bbdfSmrg BoxPtr extents, pbox, firstBox, lastBox; 234835c4bbdfSmrg BoxRec tmpBox; 234935c4bbdfSmrg int y, nbox; 235035c4bbdfSmrg 235135c4bbdfSmrg extents = RegionExtents(reg); 235235c4bbdfSmrg nbox = RegionNumRects(reg); 235335c4bbdfSmrg pbox = RegionRects(reg); 235435c4bbdfSmrg 235535c4bbdfSmrg if ((dy > 0) && (dy < (extents->y2 - extents->y1))) { 235635c4bbdfSmrg *ydir = -1; 235735c4bbdfSmrg if (nbox > 1) { 235835c4bbdfSmrg firstBox = pbox; 235935c4bbdfSmrg lastBox = pbox + nbox - 1; 236035c4bbdfSmrg while ((unsigned long) firstBox < (unsigned long) lastBox) { 236135c4bbdfSmrg tmpBox = *firstBox; 236235c4bbdfSmrg *firstBox = *lastBox; 236335c4bbdfSmrg *lastBox = tmpBox; 236435c4bbdfSmrg firstBox++; 236535c4bbdfSmrg lastBox--; 236635c4bbdfSmrg } 236705b261ecSmrg } 236835c4bbdfSmrg } 236935c4bbdfSmrg else 237035c4bbdfSmrg *ydir = 1; 237135c4bbdfSmrg 237235c4bbdfSmrg if ((dx > 0) && (dx < (extents->x2 - extents->x1))) { 237335c4bbdfSmrg *xdir = -1; 237435c4bbdfSmrg if (nbox > 1) { 237535c4bbdfSmrg firstBox = lastBox = pbox; 237635c4bbdfSmrg y = pbox->y1; 237735c4bbdfSmrg while (--nbox) { 237835c4bbdfSmrg pbox++; 237935c4bbdfSmrg if (pbox->y1 == y) 238035c4bbdfSmrg lastBox++; 238135c4bbdfSmrg else { 238235c4bbdfSmrg while ((unsigned long) firstBox < (unsigned long) lastBox) { 238335c4bbdfSmrg tmpBox = *firstBox; 238435c4bbdfSmrg *firstBox = *lastBox; 238535c4bbdfSmrg *lastBox = tmpBox; 238635c4bbdfSmrg firstBox++; 238735c4bbdfSmrg lastBox--; 238835c4bbdfSmrg } 238935c4bbdfSmrg 239035c4bbdfSmrg firstBox = lastBox = pbox; 239135c4bbdfSmrg y = pbox->y1; 239235c4bbdfSmrg } 239335c4bbdfSmrg } 239435c4bbdfSmrg while ((unsigned long) firstBox < (unsigned long) lastBox) { 239535c4bbdfSmrg tmpBox = *firstBox; 239635c4bbdfSmrg *firstBox = *lastBox; 239735c4bbdfSmrg *lastBox = tmpBox; 239835c4bbdfSmrg firstBox++; 239935c4bbdfSmrg lastBox--; 240035c4bbdfSmrg } 240105b261ecSmrg } 240235c4bbdfSmrg } 240335c4bbdfSmrg else 240435c4bbdfSmrg *xdir = 1; 240505b261ecSmrg 240605b261ecSmrg} 2407