#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xf86.h"
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <X11/X.h>
#include <X11/Xproto.h>
#include "xf86drm.h"
#include "misc.h"
#include "dixstruct.h"
#include "extnsionst.h"
#include "colormapst.h"
#include "cursorstr.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "servermd.h"
#define _XF86DRI_SERVER_
#include <X11/dri/xf86driproto.h>
#include "swaprep.h"
#include "xf86str.h"
#include "dri.h"
#include "sarea.h"
#include "dristruct.h"
#include "xf86.h"
#include "xf86drm.h"
#include "mi.h"
#include "mipointer.h"
#include "xf86_OSproc.h"
#include "inputstr.h"
#include "xf86VGAarbiter.h"
static int DRIEntPrivIndex = -1;
static DevPrivateKeyRec DRIScreenPrivKeyRec;
#define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
static DevPrivateKeyRec DRIWindowPrivKeyRec;
#define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
static unsigned long DRIGeneration = 0;
static unsigned int DRIDrawableValidationStamp = 0;
static RESTYPE DRIDrawablePrivResType;
static RESTYPE DRIContextPrivResType;
static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv);
drmServerInfo DRIDRMServerInfo;
#define DRI_MSG_VERBOSITY 1
static void
DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
{
va_list ap;
va_start(ap, format);
xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap);
va_end(ap);
}
static void
DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv)
{
if (pDRIEntPriv->pLSAREA != NULL) {
drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize);
pDRIEntPriv->pLSAREA = NULL;
}
if (pDRIEntPriv->hLSAREA != 0) {
drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA);
}
if (pDRIEntPriv->drmFD >= 0) {
drmClose(pDRIEntPriv->drmFD);
pDRIEntPriv->drmFD = 0;
}
}
int
DRIMasterFD(ScrnInfoPtr pScrn)
{
return DRI_ENT_PRIV(pScrn)->drmFD;
}
void *
DRIMasterSareaPointer(ScrnInfoPtr pScrn)
{
return DRI_ENT_PRIV(pScrn)->pLSAREA;
}
drm_handle_t
DRIMasterSareaHandle(ScrnInfoPtr pScrn)
{
return DRI_ENT_PRIV(pScrn)->hLSAREA;
}
Bool
DRIOpenDRMMaster(ScrnInfoPtr pScrn,
unsigned long sAreaSize,
const char *busID,
const char *drmDriverName)
{
drmSetVersion saveSv, sv;
Bool drmWasAvailable;
DRIEntPrivPtr pDRIEntPriv;
DRIEntPrivRec tmp;
drmVersionPtr drmlibv;
int drmlibmajor, drmlibminor;
const char *openBusID;
int count;
int err;
if (DRIEntPrivIndex == -1)
DRIEntPrivIndex = xf86AllocateEntityPrivateIndex();
pDRIEntPriv = DRI_ENT_PRIV(pScrn);
if (pDRIEntPriv && pDRIEntPriv->drmFD != -1)
return TRUE;
drmWasAvailable = drmAvailable();
memset(&tmp, 0, sizeof(tmp));
drmlibmajor = 1;
drmlibminor = 0;
if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
drmlibv = drmGetLibVersion(-1);
if (drmlibv != NULL) {
drmlibmajor = drmlibv->version_major;
drmlibminor = drmlibv->version_minor;
drmFreeVersion(drmlibv);
}
}
openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL;
tmp.drmFD = -1;
sv.drm_di_major = 1;
sv.drm_di_minor = 1;
sv.drm_dd_major = -1;
saveSv = sv;
count = 10;
while (count--) {
tmp.drmFD = drmOpen(drmDriverName, openBusID);
if (tmp.drmFD < 0) {
DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n");
goto out_err;
}
err = drmSetInterfaceVersion(tmp.drmFD, &sv);
if (err != -EPERM)
break;
sv = saveSv;
drmClose(tmp.drmFD);
tmp.drmFD = -1;
usleep(100000);
}
if (tmp.drmFD <= 0) {
DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n");
goto out_err;
}
if (!drmWasAvailable) {
DRIDrvMsg(-1, X_INFO,
"[drm] loaded kernel module for \"%s\" driver.\n",
drmDriverName);
}
if (err != 0) {
sv.drm_di_major = 1;
sv.drm_di_minor = 0;
}
DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n",
sv.drm_di_major, sv.drm_di_minor);
if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1)
err = 0;
else
err = drmSetBusid(tmp.drmFD, busID);
if (err) {
DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n");
goto out_err;
}
if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM,
DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) {
DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n");
tmp.hLSAREA = 0;
goto out_err;
}
if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize,
(drmAddressPtr)(&tmp.pLSAREA)) < 0) {
DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n");
tmp.pLSAREA = NULL;
goto out_err;
}
memset(tmp.pLSAREA, 0, sAreaSize);
tmp.resOwner = NULL;
if (!pDRIEntPriv)
pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1);
if (!pDRIEntPriv) {
DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for "
"DRM device.\n");
goto out_err;
}
*pDRIEntPriv = tmp;
xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr =
pDRIEntPriv;
DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n");
return TRUE;
out_err:
DRIOpenDRMCleanup(&tmp);
return FALSE;
}
static void
DRIClipNotifyAllDrawables(ScreenPtr pScreen);
static void
dri_crtc_notify(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIClipNotifyAllDrawables(pScreen);
xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
xf86_crtc_notify(pScreen);
pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify);
}
Bool
DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
{
DRIScreenPrivPtr pDRIPriv;
drm_context_t * reserved;
int reserved_count;
int i;
DRIEntPrivPtr pDRIEntPriv;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
DRIContextFlags flags = 0;
DRIContextPrivPtr pDRIContextPriv;
if (noXFree86DRIExtension) {
DRIDrvMsg(pScreen->myNum, X_WARNING,
"Direct rendering has been disabled.\n");
return FALSE;
}
if (!xf86VGAarbiterAllowDRI(pScreen)) {
DRIDrvMsg(pScreen->myNum, X_WARNING,
"Direct rendering is not supported when VGA arb is necessary for the device\n");
return FALSE;
}
#ifdef PANORAMIX
if (!noPanoramiXExtension) {
DRIDrvMsg(pScreen->myNum, X_WARNING,
"Direct rendering is not supported when Xinerama is enabled\n");
return FALSE;
}
#endif
if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize,
pDRIInfo->busIdString,
pDRIInfo->drmDriverName))
return FALSE;
pDRIEntPriv = DRI_ENT_PRIV(pScrn);
if (DRIGeneration != serverGeneration)
DRIGeneration = serverGeneration;
if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
return FALSE;
if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
return FALSE;
pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec));
if (!pDRIPriv) {
dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
return FALSE;
}
dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv);
pDRIPriv->drmFD = pDRIEntPriv->drmFD;
pDRIPriv->directRenderingSupport = TRUE;
pDRIPriv->pDriverInfo = pDRIInfo;
pDRIPriv->nrWindows = 0;
pDRIPriv->nrWindowsVisible = 0;
pDRIPriv->fullscreen = NULL;
pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx;
pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv;
pDRIPriv->grabbedDRILock = FALSE;
pDRIPriv->drmSIGIOHandlerInstalled = FALSE;
*pDRMFD = pDRIPriv->drmFD;
if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) {
if (drmAddMap( pDRIPriv->drmFD,
0,
pDRIPriv->pDriverInfo->SAREASize,
DRM_SHM,
0,
&pDRIPriv->hSAREA) < 0)
{
pDRIPriv->directRenderingSupport = FALSE;
dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
drmClose(pDRIPriv->drmFD);
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] drmAddMap failed\n");
return FALSE;
}
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] added %d byte SAREA at %p\n",
pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA);
if (drmMap( pDRIPriv->drmFD,
pDRIPriv->hSAREA,
pDRIPriv->pDriverInfo->SAREASize,
(drmAddressPtr)(&pDRIPriv->pSAREA)) < 0)
{
pDRIPriv->directRenderingSupport = FALSE;
dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
drmClose(pDRIPriv->drmFD);
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] drmMap failed\n");
return FALSE;
}
DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
pDRIPriv->hSAREA, pDRIPriv->pSAREA);
memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
} else {
DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock "
"SAREA also for drawables.\n");
pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA;
pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA;
pDRIEntPriv->sAreaGrabbed = TRUE;
}
pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA;
pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA;
if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer)
{
if (drmAddMap( pDRIPriv->drmFD,
(uintptr_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress,
pDRIPriv->pDriverInfo->frameBufferSize,
DRM_FRAME_BUFFER,
0,
&pDRIPriv->pDriverInfo->hFrameBuffer) < 0)
{
pDRIPriv->directRenderingSupport = FALSE;
dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize);
drmClose(pDRIPriv->drmFD);
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] drmAddMap failed\n");
return FALSE;
}
DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n",
pDRIPriv->pDriverInfo->hFrameBuffer);
} else {
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] framebuffer mapped by ddx driver\n");
}
if (pDRIEntPriv->resOwner == NULL) {
pDRIEntPriv->resOwner = pScreen;
if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
&reserved_count))) {
int i;
void *tag;
for (i = 0; i < reserved_count; i++) {
tag = DRICreateContextPrivFromHandle(pScreen,
reserved[i],
DRI_CONTEXT_RESERVED);
drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag);
}
drmFreeReservedContextList(reserved);
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] added %d reserved context%s for kernel\n",
reserved_count, reserved_count > 1 ? "s" : "");
}
}
if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) ||
(pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"Invalid max drawable table size set by driver: %d\n",
pDRIPriv->pDriverInfo->maxDrawableTableEntry);
}
for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
pDRIPriv->DRIDrawables[i] = NULL;
pDRIPriv->pSAREA->drawableTable[i].stamp = 0;
pDRIPriv->pSAREA->drawableTable[i].flags = 0;
}
pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount;
pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext;
if (!pDRIEntPriv->keepFDOpen)
pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen;
pDRIEntPriv->refCount++;
switch (pDRIInfo->driverSwapMethod) {
case DRI_KERNEL_SWAP:
flags = DRI_CONTEXT_2DONLY;
break;
case DRI_HIDE_X_CONTEXT:
flags = DRI_CONTEXT_PRESERVED;
break;
}
if (!(pDRIContextPriv = DRICreateContextPriv(pScreen,
&pDRIPriv->myContext,
flags))) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"failed to create server context\n");
return FALSE;
}
pDRIPriv->myContextPriv = pDRIContextPriv;
DRIDrvMsg(pScreen->myNum, X_INFO,
"X context handle = %p\n", pDRIPriv->myContext);
DRILock(pScreen, 0);
pDRIPriv->grabbedDRILock = TRUE;
pDRIPriv->hiddenContextStore = NULL;
pDRIPriv->partial3DContextStore = NULL;
switch(pDRIInfo->driverSwapMethod) {
case DRI_HIDE_X_CONTEXT:
pDRIPriv->hiddenContextStore
= (void *)calloc(1, pDRIInfo->contextSize);
if (!pDRIPriv->hiddenContextStore) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"failed to allocate hidden context\n");
DRIDestroyContextPriv(pDRIContextPriv);
return FALSE;
}
pDRIPriv->partial3DContextStore
= (void *)calloc(1, pDRIInfo->contextSize);
if (!pDRIPriv->partial3DContextStore) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[DRI] failed to allocate partial 3D context\n");
free(pDRIPriv->hiddenContextStore);
DRIDestroyContextPriv(pDRIContextPriv);
return FALSE;
}
if (pDRIInfo->SwapContext) {
(*pDRIInfo->SwapContext)(
pScreen,
DRI_NO_SYNC,
DRI_2D_CONTEXT,
pDRIPriv->hiddenContextStore,
DRI_NO_CONTEXT,
NULL);
}
case DRI_SERVER_SWAP:
if (!(pDRIPriv->drmSIGIOHandlerInstalled =
drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[drm] failed to setup DRM signal handler\n");
free(pDRIPriv->hiddenContextStore);
free(pDRIPriv->partial3DContextStore);
DRIDestroyContextPriv(pDRIContextPriv);
return FALSE;
} else {
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] installed DRM signal handler\n");
}
default:
break;
}
return TRUE;
}
Bool
DRIFinishScreenInit(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
if (pDRIInfo->wrap.ValidateTree) {
pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree;
}
if (pDRIInfo->wrap.PostValidateTree) {
pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree;
}
if (pDRIInfo->wrap.WindowExposures) {
pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures;
}
pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
pScreen->DestroyWindow = DRIDestroyWindow;
pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen,
dri_crtc_notify);
if (pDRIInfo->wrap.CopyWindow) {
pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow;
}
if (pDRIInfo->wrap.ClipNotify) {
pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify;
}
if (pDRIInfo->wrap.AdjustFrame) {
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame;
pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame;
}
pDRIPriv->wrapped = TRUE;
DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n");
return TRUE;
}
void
DRICloseScreen(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIInfoPtr pDRIInfo;
drm_context_t * reserved;
int reserved_count;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn);
Bool closeMaster;
if (pDRIPriv) {
pDRIInfo = pDRIPriv->pDriverInfo;
if (pDRIPriv->wrapped) {
if (pDRIInfo->wrap.ValidateTree) {
pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
pDRIPriv->wrap.ValidateTree = NULL;
}
if (pDRIInfo->wrap.PostValidateTree) {
pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
pDRIPriv->wrap.PostValidateTree = NULL;
}
if (pDRIInfo->wrap.WindowExposures) {
pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
pDRIPriv->wrap.WindowExposures = NULL;
}
if (pDRIPriv->DestroyWindow) {
pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
pDRIPriv->DestroyWindow = NULL;
}
xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
if (pDRIInfo->wrap.CopyWindow) {
pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
pDRIPriv->wrap.CopyWindow = NULL;
}
if (pDRIInfo->wrap.ClipNotify) {
pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
pDRIPriv->wrap.ClipNotify = NULL;
}
if (pDRIInfo->wrap.AdjustFrame) {
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame;
pDRIPriv->wrap.AdjustFrame = NULL;
}
pDRIPriv->wrapped = FALSE;
}
if (pDRIPriv->drmSIGIOHandlerInstalled) {
if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[drm] failed to remove DRM signal handler\n");
}
}
if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) {
DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv);
}
if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"failed to destroy server context\n");
}
if (pDRIEntPriv->resOwner == pScreen) {
pDRIEntPriv->resOwner = NULL;
if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
&reserved_count))) {
int i;
for (i = 0; i < reserved_count; i++) {
DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
reserved[i]));
}
drmFreeReservedContextList(reserved);
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] removed %d reserved context%s for kernel\n",
reserved_count, reserved_count > 1 ? "s" : "");
}
}
drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext);
pDRIPriv->pLockRefCount = NULL;
closeMaster = (--pDRIEntPriv->refCount == 0) &&
!pDRIEntPriv->keepFDOpen;
if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) {
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] unmapping %d bytes of SAREA %p at %p\n",
pDRIInfo->SAREASize,
pDRIPriv->hSAREA,
pDRIPriv->pSAREA);
if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[drm] unable to unmap %d bytes"
" of SAREA %p at %p\n",
pDRIInfo->SAREASize,
pDRIPriv->hSAREA,
pDRIPriv->pSAREA);
}
} else {
pDRIEntPriv->sAreaGrabbed = FALSE;
}
if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) {
drmClose(pDRIPriv->drmFD);
if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) {
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] Closed DRM master.\n");
pDRIEntPriv->drmFD = -1;
}
}
free(pDRIPriv);
dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
}
}
#define DRM_MSG_VERBOSITY 3
static int dri_drm_debug_print(const char *format, va_list ap)
{
xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
return 0;
}
static void dri_drm_get_perms(gid_t *group, mode_t *mode)
{
*group = xf86ConfigDRI.group;
*mode = xf86ConfigDRI.mode;
}
drmServerInfo DRIDRMServerInfo = {
dri_drm_debug_print,
xf86LoadKernelModule,
dri_drm_get_perms,
};
Bool
DRIExtensionInit(void)
{
if (DRIGeneration != serverGeneration) {
return FALSE;
}
DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
"DRIDrawable");
DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete,
"DRIContext");
if (!DRIDrawablePrivResType || !DRIContextPrivResType)
return FALSE;
RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL);
return TRUE;
}
void
DRIReset(void)
{
}
Bool
DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv)
*isCapable = pDRIPriv->directRenderingSupport;
else
*isCapable = FALSE;
return TRUE;
}
Bool
DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
*hSAREA = pDRIPriv->hSAREA;
*busIdString = pDRIPriv->pDriverInfo->busIdString;
return TRUE;
}
Bool
DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
return TRUE;
}
Bool
DRICloseConnection(ScreenPtr pScreen)
{
return TRUE;
}
Bool
DRIGetClientDriverName(ScreenPtr pScreen,
int *ddxDriverMajorVersion,
int *ddxDriverMinorVersion,
int *ddxDriverPatchVersion,
char **clientDriverName)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
*ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion;
*ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion;
*ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion;
*clientDriverName = pDRIPriv->pDriverInfo->clientDriverName;
return TRUE;
}
DRIContextPrivPtr
DRICreateContextPriv(ScreenPtr pScreen,
drm_context_t * pHWContext,
DRIContextFlags flags)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) {
return NULL;
}
return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags);
}
DRIContextPrivPtr
DRICreateContextPrivFromHandle(ScreenPtr pScreen,
drm_context_t hHWContext,
DRIContextFlags flags)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIContextPrivPtr pDRIContextPriv;
int contextPrivSize;
contextPrivSize = sizeof(DRIContextPrivRec) +
pDRIPriv->pDriverInfo->contextSize;
if (!(pDRIContextPriv = calloc(1, contextPrivSize))) {
return NULL;
}
pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1);
drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv);
pDRIContextPriv->hwContext = hHWContext;
pDRIContextPriv->pScreen = pScreen;
pDRIContextPriv->flags = flags;
pDRIContextPriv->valid3D = FALSE;
if (flags & DRI_CONTEXT_2DONLY) {
if (drmSetContextFlags(pDRIPriv->drmFD,
hHWContext,
DRM_CONTEXT_2DONLY)) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[drm] failed to set 2D context flag\n");
DRIDestroyContextPriv(pDRIContextPriv);
return NULL;
}
}
if (flags & DRI_CONTEXT_PRESERVED) {
if (drmSetContextFlags(pDRIPriv->drmFD,
hHWContext,
DRM_CONTEXT_PRESERVED)) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[drm] failed to set preserved flag\n");
DRIDestroyContextPriv(pDRIContextPriv);
return NULL;
}
}
return pDRIContextPriv;
}
Bool
DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv)
{
DRIScreenPrivPtr pDRIPriv;
if (!pDRIContextPriv) return TRUE;
pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) {
if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext))
return FALSE;
}
drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext);
free(pDRIContextPriv);
return TRUE;
}
static Bool
DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIContextPrivPtr pDRIContextPriv;
void *contextStore;
if (!(pDRIContextPriv =
DRICreateContextPriv(pScreen,
&pDRIPriv->pSAREA->dummy_context, 0))) {
return FALSE;
}
contextStore = DRIGetContextStore(pDRIContextPriv);
if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) {
if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL,
pDRIPriv->pSAREA->dummy_context,
NULL,
(DRIContextType)(long)contextStore)) {
DRIDestroyContextPriv(pDRIContextPriv);
return FALSE;
}
}
pDRIPriv->dummyCtxPriv = pDRIContextPriv;
return TRUE;
}
static void
DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv;
void *contextStore;
if (!pDRIContextPriv) return;
if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) {
contextStore = DRIGetContextStore(pDRIContextPriv);
pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
pDRIContextPriv->hwContext,
(DRIContextType)(long)contextStore);
}
DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv);
pDRIPriv->dummyCtxPriv = NULL;
}
Bool
DRICreateContext(ScreenPtr pScreen, VisualPtr visual,
XID context, drm_context_t * pHWContext)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIContextPrivPtr pDRIContextPriv;
void *contextStore;
if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) {
if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) {
DRIDrvMsg(pScreen->myNum, X_INFO,
"[drm] Could not create dummy context\n");
return FALSE;
}
}
if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) {
return FALSE;
}
contextStore = DRIGetContextStore(pDRIContextPriv);
if (pDRIPriv->pDriverInfo->CreateContext) {
if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL,
*pHWContext, NULL,
(DRIContextType)(long)contextStore))) {
DRIDestroyContextPriv(pDRIContextPriv);
return FALSE;
}
}
AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv);
return TRUE;
}
Bool
DRIDestroyContext(ScreenPtr pScreen, XID context)
{
FreeResourceByType(context, DRIContextPrivResType, FALSE);
return TRUE;
}
Bool
DRIContextPrivDelete(pointer pResource, XID id)
{
DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource;
DRIScreenPrivPtr pDRIPriv;
void *contextStore;
pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
if (pDRIPriv->pDriverInfo->DestroyContext) {
contextStore = DRIGetContextStore(pDRIContextPriv);
pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
pDRIContextPriv->hwContext,
(DRIContextType)(long)contextStore);
}
return DRIDestroyContextPriv(pDRIContextPriv);
}
static void
DRIClipNotifyAllDrawables(ScreenPtr pScreen)
{
int i;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++;
}
}
static void
DRITransitionToSharedBuffers(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
DRIClipNotifyAllDrawables( pScreen );
if (pDRIInfo->TransitionSingleToMulti3D)
pDRIInfo->TransitionSingleToMulti3D( pScreen );
}
static void
DRITransitionToPrivateBuffers(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
DRIClipNotifyAllDrawables( pScreen );
if (pDRIInfo->TransitionMultiToSingle3D)
pDRIInfo->TransitionMultiToSingle3D( pScreen );
}
static void
DRITransitionTo3d(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
DRIClipNotifyAllDrawables( pScreen );
if (pDRIInfo->TransitionTo3d)
pDRIInfo->TransitionTo3d( pScreen );
}
static void
DRITransitionTo2d(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
DRIClipNotifyAllDrawables( pScreen );
if (pDRIInfo->TransitionTo2d)
pDRIInfo->TransitionTo2d( pScreen );
}
static int
DRIDCNTreeTraversal(WindowPtr pWin, pointer data)
{
DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
if (pDRIDrawablePriv) {
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (RegionNumRects(&pWin->clipList) > 0) {
WindowPtr *pDRIWindows = (WindowPtr*)data;
int i = 0;
while (pDRIWindows[i])
i++;
pDRIWindows[i] = pWin;
pDRIPriv->nrWalked++;
}
if (pDRIPriv->nrWindows == pDRIPriv->nrWalked)
return WT_STOPWALKING;
}
return WT_WALKCHILDREN;
}
static void
DRIDriverClipNotify(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv->pDriverInfo->ClipNotify) {
WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows);
DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
if (pDRIPriv->nrWindows > 0) {
pDRIPriv->nrWalked = 0;
TraverseTree(pScreen->root, DRIDCNTreeTraversal,
(pointer)pDRIWindows);
}
pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows);
free(pDRIWindows);
}
}
static void
DRIIncreaseNumberVisible(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
switch (++pDRIPriv->nrWindowsVisible) {
case 1:
DRITransitionTo3d( pScreen );
break;
case 2:
DRITransitionToSharedBuffers( pScreen );
break;
default:
break;
}
DRIDriverClipNotify(pScreen);
}
static void
DRIDecreaseNumberVisible(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
switch (--pDRIPriv->nrWindowsVisible) {
case 0:
DRITransitionTo2d( pScreen );
break;
case 1:
DRITransitionToPrivateBuffers( pScreen );
break;
default:
break;
}
DRIDriverClipNotify(pScreen);
}
Bool
DRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable,
drm_drawable_t * hHWDrawable)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv;
WindowPtr pWin;
if (pDrawable->type == DRAWABLE_WINDOW) {
pWin = (WindowPtr)pDrawable;
if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
pDRIDrawablePriv->refCount++;
if (!pDRIDrawablePriv->hwDrawable) {
drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable);
}
}
else {
if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) {
return FALSE;
}
if (drmCreateDrawable(pDRIPriv->drmFD,
&pDRIDrawablePriv->hwDrawable)) {
free(pDRIDrawablePriv);
return FALSE;
}
pDRIDrawablePriv->pScreen = pScreen;
pDRIDrawablePriv->refCount = 1;
pDRIDrawablePriv->drawableIndex = -1;
pDRIDrawablePriv->nrects = RegionNumRects(&pWin->clipList);
dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey,
pDRIDrawablePriv);
pDRIPriv->nrWindows++;
if (pDRIDrawablePriv->nrects)
DRIIncreaseNumberVisible(pScreen);
}
AddResource(FakeClientID(client->index), DRIDrawablePrivResType,
(pointer)(intptr_t)pDrawable->id);
if (pDRIDrawablePriv->hwDrawable) {
drmUpdateDrawableInfo(pDRIPriv->drmFD,
pDRIDrawablePriv->hwDrawable,
DRM_DRAWABLE_CLIPRECTS,
RegionNumRects(&pWin->clipList),
RegionRects(&pWin->clipList));
*hHWDrawable = pDRIDrawablePriv->hwDrawable;
}
}
else if (pDrawable->type != DRAWABLE_PIXMAP) {
return FALSE;
}
return TRUE;
}
static void
DRIDrawablePrivDestroy(WindowPtr pWin)
{
DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
ScreenPtr pScreen;
DRIScreenPrivPtr pDRIPriv;
if (!pDRIDrawablePriv)
return;
pScreen = pWin->drawable.pScreen;
pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIDrawablePriv->drawableIndex != -1) {
pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
= DRIDrawableValidationStamp++;
pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
}
pDRIPriv->nrWindows--;
if (pDRIDrawablePriv->nrects)
DRIDecreaseNumberVisible(pScreen);
drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable);
free(pDRIDrawablePriv);
dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
}
static Bool
DRIDestroyDrawableCB(pointer value, XID id, pointer data)
{
if (value == data) {
FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
return TRUE;
}
return FALSE;
}
Bool
DRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable)
{
if (pDrawable->type == DRAWABLE_WINDOW) {
LookupClientResourceComplex(client, DRIDrawablePrivResType,
DRIDestroyDrawableCB,
(pointer)(intptr_t)pDrawable->id);
}
else {
return FALSE;
}
return TRUE;
}
Bool
DRIDrawablePrivDelete(pointer pResource, XID id)
{
WindowPtr pWin;
int rc;
id = (XID)(intptr_t)pResource;
rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess);
if (rc == Success) {
DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
if (!pDRIDrwPriv)
return FALSE;
if (--pDRIDrwPriv->refCount == 0)
DRIDrawablePrivDestroy(pWin);
return TRUE;
}
else {
return FALSE;
}
}
Bool
DRIGetDrawableInfo(ScreenPtr pScreen,
DrawablePtr pDrawable,
unsigned int* index,
unsigned int* stamp,
int* X,
int* Y,
int* W,
int* H,
int* numClipRects,
drm_clip_rect_t ** pClipRects,
int* backX,
int* backY,
int* numBackClipRects,
drm_clip_rect_t ** pBackClipRects)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv;
WindowPtr pWin, pOldWin;
int i;
#if 0
printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry);
#endif
if (pDrawable->type == DRAWABLE_WINDOW) {
pWin = (WindowPtr)pDrawable;
if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
if (pDRIDrawablePriv->drawableIndex == -1) {
i = 0;
while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
if (!(pDRIPriv->DRIDrawables[i])) {
pDRIPriv->DRIDrawables[i] = pDrawable;
pDRIDrawablePriv->drawableIndex = i;
pDRIPriv->pSAREA->drawableTable[i].stamp =
DRIDrawableValidationStamp++;
break;
}
i++;
}
if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
unsigned int oldestStamp = ~0;
int oldestIndex = 0;
i = pDRIPriv->pDriverInfo->maxDrawableTableEntry;
while (i--) {
if (pDRIPriv->pSAREA->drawableTable[i].stamp <
oldestStamp) {
oldestIndex = i;
oldestStamp =
pDRIPriv->pSAREA->drawableTable[i].stamp;
}
}
pDRIDrawablePriv->drawableIndex = oldestIndex;
pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex];
pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin);
pOldDrawPriv->drawableIndex = -1;
pDRIPriv->DRIDrawables[oldestIndex] = pDrawable;
pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp =
DRIDrawableValidationStamp++;
if (oldestStamp > DRIDrawableValidationStamp) {
for( i=0;
i < pDRIPriv->pDriverInfo->maxDrawableTableEntry;
i++) {
pDRIPriv->pSAREA->drawableTable[i].stamp =
DRIDrawableValidationStamp++;
}
}
}
if (pDRIPriv->pDriverInfo->SetDrawableIndex)
pDRIPriv->pDriverInfo->SetDrawableIndex(pWin,
pDRIDrawablePriv->drawableIndex);
if ((pWin->viewable) &&
(pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS))
{
(*pDRIPriv->pDriverInfo->InitBuffers)(pWin,
&pWin->clipList, pDRIDrawablePriv->drawableIndex);
}
}
*index = pDRIDrawablePriv->drawableIndex;
*stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp;
*X = (int)(pWin->drawable.x);
*Y = (int)(pWin->drawable.y);
#if 0
*W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1);
*H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
#endif
*W = (int)(pWin->drawable.width);
*H = (int)(pWin->drawable.height);
*numClipRects = RegionNumRects(&pWin->clipList);
*pClipRects = (drm_clip_rect_t *)RegionRects(&pWin->clipList);
if (!*numClipRects && pDRIPriv->fullscreen) {
pDRIPriv->fullscreen_rect.x1 = *X;
pDRIPriv->fullscreen_rect.y1 = *Y;
pDRIPriv->fullscreen_rect.x2 = *X + *W;
pDRIPriv->fullscreen_rect.y2 = *Y + *H;
*numClipRects = 1;
*pClipRects = &pDRIPriv->fullscreen_rect;
}
*backX = *X;
*backY = *Y;
if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) {
int x0 = *X;
int y0 = *Y;
int x1 = x0 + *W;
int y1 = y0 + *H;
if (x0 < 0) x0 = 0;
if (y0 < 0) y0 = 0;
if (x1 > pScreen->width) x1 = pScreen->width;
if (y1 > pScreen->height) y1 = pScreen->height;
if (y0 >= y1 || x0 >= x1) {
*numBackClipRects = 0;
*pBackClipRects = NULL;
} else {
pDRIPriv->private_buffer_rect.x1 = x0;
pDRIPriv->private_buffer_rect.y1 = y0;
pDRIPriv->private_buffer_rect.x2 = x1;
pDRIPriv->private_buffer_rect.y2 = y1;
*numBackClipRects = 1;
*pBackClipRects = &(pDRIPriv->private_buffer_rect);
}
} else {
*numBackClipRects = 0;
*pBackClipRects = 0;
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
return TRUE;
}
Bool
DRIGetDeviceInfo(ScreenPtr pScreen,
drm_handle_t * hFrameBuffer,
int* fbOrigin,
int* fbSize,
int* fbStride,
int* devPrivateSize,
void** pDevPrivate)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
*hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer;
*fbOrigin = 0;
*fbSize = pDRIPriv->pDriverInfo->frameBufferSize;
*fbStride = pDRIPriv->pDriverInfo->frameBufferStride;
*devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize;
*pDevPrivate = pDRIPriv->pDriverInfo->devPrivate;
return TRUE;
}
DRIInfoPtr
DRICreateInfoRec(void)
{
DRIInfoPtr inforec = (DRIInfoPtr)calloc(1, sizeof(DRIInfoRec));
if (!inforec) return NULL;
inforec->busIdString = NULL;
inforec->wrap.WakeupHandler = DRIDoWakeupHandler;
inforec->wrap.BlockHandler = DRIDoBlockHandler;
inforec->wrap.WindowExposures = DRIWindowExposures;
inforec->wrap.CopyWindow = DRICopyWindow;
inforec->wrap.ValidateTree = DRIValidateTree;
inforec->wrap.PostValidateTree = DRIPostValidateTree;
inforec->wrap.ClipNotify = DRIClipNotify;
inforec->wrap.AdjustFrame = DRIAdjustFrame;
inforec->TransitionTo2d = 0;
inforec->TransitionTo3d = 0;
inforec->SetDrawableIndex = 0;
return inforec;
}
void
DRIDestroyInfoRec(DRIInfoPtr DRIInfo)
{
free(DRIInfo->busIdString);
free((char*)DRIInfo);
}
void
DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask)
{
int i;
for (i = 0; i < screenInfo.numScreens; i++) {
ScreenPtr pScreen = screenInfo.screens[i];
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv &&
pDRIPriv->pDriverInfo->wrap.WakeupHandler)
(*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData,
result, pReadmask);
}
}
void
DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
{
int i;
for (i = 0; i < screenInfo.numScreens; i++) {
ScreenPtr pScreen = screenInfo.screens[i];
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv &&
pDRIPriv->pDriverInfo->wrap.BlockHandler)
(*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData,
pTimeout, pReadmask);
}
}
void
DRIDoWakeupHandler(int screenNum, pointer wakeupData,
unsigned long result, pointer pReadmask)
{
ScreenPtr pScreen = screenInfo.screens[screenNum];
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRILock(pScreen, 0);
if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
(*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
DRI_3D_SYNC,
DRI_2D_CONTEXT,
pDRIPriv->partial3DContextStore,
DRI_2D_CONTEXT,
pDRIPriv->hiddenContextStore);
}
}
void
DRIDoBlockHandler(int screenNum, pointer blockData,
pointer pTimeout, pointer pReadmask)
{
ScreenPtr pScreen = screenInfo.screens[screenNum];
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
(*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
DRI_2D_SYNC,
DRI_NO_CONTEXT,
NULL,
DRI_2D_CONTEXT,
pDRIPriv->partial3DContextStore);
}
if (pDRIPriv->windowsTouched)
DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1);
pDRIPriv->windowsTouched = FALSE;
DRIUnlock(pScreen);
}
void
DRISwapContext(int drmFD, void *oldctx, void *newctx)
{
DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx;
DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx;
ScreenPtr pScreen = newContext->pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
void* oldContextStore = NULL;
DRIContextType oldContextType;
void* newContextStore = NULL;
DRIContextType newContextType;
DRISyncType syncType;
#ifdef DEBUG
static int count = 0;
if (!newContext) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[DRI] Context Switch Error: oldContext=%x, newContext=%x\n",
oldContext, newContext);
return;
}
if (!count || !(count % 1)) {
DRIDrvMsg(pScreen->myNum, X_INFO,
"[DRI] Context switch %5d from %p/0x%08x (%d)\n",
count,
oldContext,
oldContext ? oldContext->flags : 0,
oldContext ? oldContext->hwContext : -1);
DRIDrvMsg(pScreen->myNum, X_INFO,
"[DRI] Context switch %5d to %p/0x%08x (%d)\n",
count,
newContext,
newContext ? newContext->flags : 0,
newContext ? newContext->hwContext : -1);
}
++count;
#endif
if (!pDRIPriv->pDriverInfo->SwapContext) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[DRI] DDX driver missing context swap call back\n");
return;
}
if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
if (oldContext) {
oldContextStore = DRIGetContextStore(oldContext);
oldContext->valid3D = TRUE;
oldContextType = DRI_3D_CONTEXT;
} else {
oldContextType = DRI_NO_CONTEXT;
}
newContextStore = DRIGetContextStore(newContext);
if ((newContext->valid3D) &&
(newContext->hwContext != pDRIPriv->myContext)) {
newContextType = DRI_3D_CONTEXT;
}
else {
newContextType = DRI_2D_CONTEXT;
}
syncType = DRI_3D_SYNC;
}
else {
if (newContext->flags & DRI_CONTEXT_2DONLY) {
oldContextStore = DRIGetContextStore(oldContext);
oldContextType = DRI_2D_CONTEXT;
newContextStore = DRIGetContextStore(newContext);
newContextType = DRI_2D_CONTEXT;
syncType = DRI_3D_SYNC;
pDRIPriv->lastPartial3DContext = oldContext;
}
else if (oldContext->flags & DRI_CONTEXT_2DONLY) {
if (pDRIPriv->lastPartial3DContext == newContext) {
oldContextStore = DRIGetContextStore(oldContext);
oldContextType = DRI_2D_CONTEXT;
newContextStore = DRIGetContextStore(newContext);
newContextType = DRI_2D_CONTEXT;
syncType = DRI_2D_SYNC;
}
else {
oldContextStore = DRIGetContextStore(oldContext);
newContextStore =
DRIGetContextStore(pDRIPriv->lastPartial3DContext);
(*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
DRI_2D_SYNC,
DRI_2D_CONTEXT,
oldContextStore,
DRI_2D_CONTEXT,
newContextStore);
oldContextStore = newContextStore;
oldContext->valid3D = TRUE;
oldContextType = DRI_3D_CONTEXT;
newContextStore = DRIGetContextStore(newContext);
if ((newContext->valid3D) &&
(newContext->hwContext != pDRIPriv->myContext)) {
newContextType = DRI_3D_CONTEXT;
}
else {
newContextType = DRI_2D_CONTEXT;
}
syncType = DRI_NO_SYNC;
}
}
else {
oldContextStore = newContextStore;
oldContext->valid3D = TRUE;
oldContextType = DRI_3D_CONTEXT;
newContextStore = DRIGetContextStore(newContext);
if ((newContext->valid3D) &&
(newContext->hwContext != pDRIPriv->myContext)) {
newContextType = DRI_3D_CONTEXT;
}
else {
newContextType = DRI_2D_CONTEXT;
}
syncType = DRI_3D_SYNC;
}
}
(*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
syncType,
oldContextType,
oldContextStore,
newContextType,
newContextStore);
}
void*
DRIGetContextStore(DRIContextPrivPtr context)
{
return((void *)context->pContextStore);
}
void
DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
if(pDRIDrawablePriv) {
(*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn,
pDRIDrawablePriv->drawableIndex);
}
if (pDRIPriv && pDRIPriv->wrap.WindowExposures) {
pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
(*pScreen->WindowExposures)(pWin, prgn, bsreg);
pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
pScreen->WindowExposures = DRIWindowExposures;
}
}
static int
DRITreeTraversal(WindowPtr pWin, pointer data)
{
DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
if(pDRIDrawablePriv) {
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if(RegionNumRects(&(pWin->clipList)) > 0) {
RegionPtr reg = (RegionPtr)data;
RegionUnion(reg, reg, &(pWin->clipList));
pDRIPriv->nrWalked++;
}
if(pDRIPriv->nrWindows == pDRIPriv->nrWalked)
return WT_STOPWALKING;
}
return WT_WALKCHILDREN;
}
Bool
DRIDestroyWindow(WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
Bool retval = TRUE;
DRIDrawablePrivDestroy(pWin);
if(pDRIPriv->DestroyWindow) {
pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
retval = (*pScreen->DestroyWindow)(pWin);
pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
pScreen->DestroyWindow = DRIDestroyWindow;
}
return retval;
}
void
DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if(!pDRIPriv) return;
if(pDRIPriv->nrWindowsVisible > 0) {
RegionRec reg;
RegionNull(®);
pDRIPriv->nrWalked = 0;
TraverseTree(pWin, DRITreeTraversal, (pointer)(®));
if(RegionNotEmpty(®)) {
RegionTranslate(®, ptOldOrg.x - pWin->drawable.x,
ptOldOrg.y - pWin->drawable.y);
RegionIntersect(®, ®, prgnSrc);
(*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®,
pDRIPriv->pDriverInfo->ddxDrawableTableEntry);
}
RegionUninit(®);
}
if(pDRIPriv->wrap.CopyWindow) {
pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
(*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
pScreen->CopyWindow = DRICopyWindow;
}
}
static void
DRIGetSecs(long *secs, long *usecs)
{
struct timeval tv;
gettimeofday(&tv, NULL);
*secs = tv.tv_sec;
*usecs = tv.tv_usec;
}
static unsigned long
DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs,
unsigned long f_secs, unsigned long f_usecs)
{
if (f_usecs < s_usecs) {
--f_secs;
f_usecs += 1000000;
}
return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000;
}
static void
DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout )
{
int count = 10000;
#if !defined(__alpha__) && !defined(__powerpc__)
char ret;
#else
int ret;
#endif
long s_secs, s_usecs;
long f_secs, f_usecs;
long msecs;
long prev = 0;
DRIGetSecs(&s_secs, &s_usecs);
do {
DRM_SPINLOCK_COUNT(lock, val, count, ret);
if (!ret) return;
DRIGetSecs(&f_secs, &f_usecs);
msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs);
if (msecs - prev < 250) count *= 2;
} while (msecs < timeout);
DRM_SPINLOCK_TAKE(lock, val);
}
static void
DRILockTree(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if(!pDRIPriv) return;
if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
(*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
DRI_2D_SYNC,
DRI_NO_CONTEXT,
NULL,
DRI_2D_CONTEXT,
pDRIPriv->partial3DContextStore);
}
DRIUnlock(pScreen);
DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000);
DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL);
if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
(*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
DRI_3D_SYNC,
DRI_2D_CONTEXT,
pDRIPriv->partial3DContextStore,
DRI_2D_CONTEXT,
pDRIPriv->hiddenContextStore);
}
}
int
DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
{
ScreenPtr pScreen = pParent->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
int returnValue = 1;
if(!pDRIPriv) return returnValue;
if(pDRIPriv->wrap.ValidateTree) {
pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
pScreen->ValidateTree = DRIValidateTree;
}
return returnValue;
}
void
DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
{
ScreenPtr pScreen;
DRIScreenPrivPtr pDRIPriv;
if (pParent) {
pScreen = pParent->drawable.pScreen;
} else {
pScreen = pChild->drawable.pScreen;
}
if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return;
if (pDRIPriv->wrap.PostValidateTree) {
pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
(*pScreen->PostValidateTree)(pParent, pChild, kind);
pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
pScreen->PostValidateTree = DRIPostValidateTree;
}
}
void
DRIClipNotify(WindowPtr pWin, int dx, int dy)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv;
if(!pDRIPriv) return;
if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
int nrects = RegionNumRects(&pWin->clipList);
if(!pDRIPriv->windowsTouched) {
DRILockTree(pScreen);
pDRIPriv->windowsTouched = TRUE;
}
if (nrects && !pDRIDrawablePriv->nrects)
DRIIncreaseNumberVisible(pScreen);
else if (!nrects && pDRIDrawablePriv->nrects)
DRIDecreaseNumberVisible(pScreen);
else
DRIDriverClipNotify(pScreen);
pDRIDrawablePriv->nrects = nrects;
pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
= DRIDrawableValidationStamp++;
drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable,
DRM_DRAWABLE_CLIPRECTS,
nrects, RegionRects(&pWin->clipList));
}
if(pDRIPriv->wrap.ClipNotify) {
pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
(*pScreen->ClipNotify)(pWin, dx, dy);
pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
pScreen->ClipNotify = DRIClipNotify;
}
}
CARD32
DRIGetDrawableIndex(WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
CARD32 index;
if (pDRIDrawablePriv) {
index = pDRIDrawablePriv->drawableIndex;
}
else {
index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry;
}
return index;
}
unsigned int
DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp;
}
void
DRIPrintDrawableLock(ScreenPtr pScreen, char *msg)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock);
}
void
DRILock(ScreenPtr pScreen, int flags)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
if (!*pDRIPriv->pLockRefCount) {
DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags);
*pDRIPriv->pLockingContext = pDRIPriv->myContext;
} else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[DRI] Locking deadlock.\n"
"\tAlready locked with context %d,\n"
"\ttrying to lock with context %d.\n",
pDRIPriv->pLockingContext,
pDRIPriv->myContext);
}
(*pDRIPriv->pLockRefCount)++;
}
void
DRIUnlock(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
if (*pDRIPriv->pLockRefCount > 0) {
if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"[DRI] Unlocking inconsistency:\n"
"\tContext %d trying to unlock lock held by context %d\n",
pDRIPriv->pLockingContext,
pDRIPriv->myContext);
}
(*pDRIPriv->pLockRefCount)--;
} else {
DRIDrvMsg(pScreen->myNum, X_ERROR,
"DRIUnlock called when not locked.\n");
return;
}
if (! *pDRIPriv->pLockRefCount)
DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext);
}
void *
DRIGetSAREAPrivate(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (!pDRIPriv) return 0;
return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec));
}
drm_context_t
DRIGetContext(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (!pDRIPriv) return 0;
return pDRIPriv->myContext;
}
void
DRIGetTexOffsetFuncs(ScreenPtr pScreen,
DRITexOffsetStartProcPtr *texOffsetStartFunc,
DRITexOffsetFinishProcPtr *texOffsetFinishFunc)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (!pDRIPriv) return;
*texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart;
*texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish;
}
DRIWrappedFuncsRec *
DRIGetWrappedFuncs(ScreenPtr pScreen)
{
return &(DRI_SCREEN_PRIV(pScreen)->wrap);
}
void
DRIQueryVersion(int *majorVersion,
int *minorVersion,
int *patchVersion)
{
*majorVersion = DRIINFO_MAJOR_VERSION;
*minorVersion = DRIINFO_MINOR_VERSION;
*patchVersion = DRIINFO_PATCH_VERSION;
}
static void
_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y)
{
pDRIPriv->pSAREA->frame.x = x;
pDRIPriv->pSAREA->frame.y = y;
pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1;
pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1;
}
void
DRIAdjustFrame(int scrnIndex, int x, int y, int flags)
{
ScreenPtr pScreen = screenInfo.screens[scrnIndex];
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
int px, py;
if (!pDRIPriv || !pDRIPriv->pSAREA) {
DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n",
pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL);
return;
}
if (pDRIPriv->fullscreen) {
pScrn->frameX0 = pDRIPriv->pSAREA->frame.x;
pScrn->frameY0 = pDRIPriv->pSAREA->frame.y;
pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1;
pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1;
miPointerGetPosition(inputInfo.pointer, &px, &py);
if (px < pScrn->frameX0) px = pScrn->frameX0;
if (px > pScrn->frameX1) px = pScrn->frameX1;
if (py < pScrn->frameY0) py = pScrn->frameY0;
if (py > pScrn->frameY1) py = pScrn->frameY1;
pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE);
return;
}
if (pDRIPriv->wrap.AdjustFrame) {
pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame;
(*pScrn->AdjustFrame)(scrnIndex, x, y, flags);
pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame;
pScrn->AdjustFrame = DRIAdjustFrame;
}
_DRIAdjustFrame(pScrn, pDRIPriv, x, y);
}
void
DRIMoveBuffersHelper(
ScreenPtr pScreen,
int dx,
int dy,
int *xdir,
int *ydir,
RegionPtr reg
)
{
BoxPtr extents, pbox, firstBox, lastBox;
BoxRec tmpBox;
int y, nbox;
extents = RegionExtents(reg);
nbox = RegionNumRects(reg);
pbox = RegionRects(reg);
if((dy > 0) && (dy < (extents->y2 - extents->y1))) {
*ydir = -1;
if(nbox > 1) {
firstBox = pbox;
lastBox = pbox + nbox - 1;
while((unsigned long)firstBox < (unsigned long)lastBox) {
tmpBox = *firstBox;
*firstBox = *lastBox;
*lastBox = tmpBox;
firstBox++;
lastBox--;
}
}
} else *ydir = 1;
if((dx > 0) && (dx < (extents->x2 - extents->x1))) {
*xdir = -1;
if(nbox > 1) {
firstBox = lastBox = pbox;
y = pbox->y1;
while(--nbox) {
pbox++;
if(pbox->y1 == y) lastBox++;
else {
while((unsigned long)firstBox < (unsigned long)lastBox) {
tmpBox = *firstBox;
*firstBox = *lastBox;
*lastBox = tmpBox;
firstBox++;
lastBox--;
}
firstBox = lastBox = pbox;
y = pbox->y1;
}
}
while((unsigned long)firstBox < (unsigned long)lastBox) {
tmpBox = *firstBox;
*firstBox = *lastBox;
*lastBox = tmpBox;
firstBox++;
lastBox--;
}
}
} else *xdir = 1;
}
char *
DRICreatePCIBusID(const struct pci_device * dev)
{
char *busID;
if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
dev->domain, dev->bus, dev->dev, dev->func) == -1)
return NULL;
return busID;
}
static void drmSIGIOHandler(int interrupt, void *closure)
{
unsigned long key;
void *value;
ssize_t count;
drm_ctx_t ctx;
typedef void (*_drmCallback)(int, void *, void *);
char buf[256];
drm_context_t old;
drm_context_t new;
void *oldctx;
void *newctx;
char *pt;
drmHashEntry *entry;
void *hash_table;
hash_table = drmGetHashTable();
if (!hash_table) return;
if (drmHashFirst(hash_table, &key, &value)) {
entry = value;
do {
#if 0
fprintf(stderr, "Trying %d\n", entry->fd);
#endif
if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) {
buf[count] = '\0';
#if 0
fprintf(stderr, "Got %s\n", buf);
#endif
for (pt = buf; *pt != ' '; ++pt);
++pt;
old = strtol(pt, &pt, 0);
new = strtol(pt, NULL, 0);
oldctx = drmGetContextTag(entry->fd, old);
newctx = drmGetContextTag(entry->fd, new);
#if 0
fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
#endif
((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
ctx.handle = new;
ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
}
} while (drmHashNext(hash_table, &key, &value));
}
}
int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
{
drmHashEntry *entry;
entry = drmGetEntry(fd);
entry->f = f;
return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
}
int drmRemoveSIGIOHandler(int fd)
{
drmHashEntry *entry = drmGetEntry(fd);
entry->f = NULL;
return xf86RemoveSIGIOHandler(fd);
}