#include "radeon.h"
#include "radeon_macros.h"
#include "radeon_dri.h"
#include "radeon_reg.h"
#include "radeon_version.h"
#include "xf86.h"
#include "xf86PciInfo.h"
#include "windowstr.h"
#include "shadowfb.h"
#define _XF86DRI_SERVER_
#include "GL/glxtokens.h"
#include "sarea.h"
#include "radeon_sarea.h"
#if defined(__alpha__)
# define DRM_PAGE_SIZE 8192
#elif defined(__ia64__)
# define DRM_PAGE_SIZE getpagesize()
#else
# define DRM_PAGE_SIZE 4096
#endif
static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen);
static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen);
static void RADEONDRITransitionTo2d(ScreenPtr pScreen);
static void RADEONDRITransitionTo3d(ScreenPtr pScreen);
static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen);
static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen);
static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
static Bool RADEONInitVisualConfigs(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
int numConfigs = 0;
__GLXvisualConfig *pConfigs = 0;
RADEONConfigPrivPtr pRADEONConfigs = 0;
RADEONConfigPrivPtr *pRADEONConfigPtrs = 0;
int i, accum, stencil, db, use_db;
use_db = !info->noBackBuffer ? 1 : 0;
switch (info->CurrentLayout.pixel_code) {
case 8:
case 15:
case 24:
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] RADEONInitVisualConfigs failed "
"(depth %d not supported). "
"Disabling DRI.\n", info->CurrentLayout.pixel_code);
return FALSE;
#define RADEON_USE_ACCUM 1
#define RADEON_USE_STENCIL 1
case 16:
numConfigs = 1;
if (RADEON_USE_ACCUM) numConfigs *= 2;
if (RADEON_USE_STENCIL) numConfigs *= 2;
if (use_db) numConfigs *= 2;
if (!(pConfigs
= (__GLXvisualConfig *)xcalloc(sizeof(__GLXvisualConfig),
numConfigs))) {
return FALSE;
}
if (!(pRADEONConfigs
= (RADEONConfigPrivPtr)xcalloc(sizeof(RADEONConfigPrivRec),
numConfigs))) {
xfree(pConfigs);
return FALSE;
}
if (!(pRADEONConfigPtrs
= (RADEONConfigPrivPtr *)xcalloc(sizeof(RADEONConfigPrivPtr),
numConfigs))) {
xfree(pConfigs);
xfree(pRADEONConfigs);
return FALSE;
}
i = 0;
for (db = 0; db <= use_db; db++) {
for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) {
for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) {
pRADEONConfigPtrs[i] = &pRADEONConfigs[i];
pConfigs[i].vid = (VisualID)(-1);
pConfigs[i].class = -1;
pConfigs[i].rgba = TRUE;
pConfigs[i].redSize = 5;
pConfigs[i].greenSize = 6;
pConfigs[i].blueSize = 5;
pConfigs[i].alphaSize = 0;
pConfigs[i].redMask = 0x0000F800;
pConfigs[i].greenMask = 0x000007E0;
pConfigs[i].blueMask = 0x0000001F;
pConfigs[i].alphaMask = 0x00000000;
if (accum) {
pConfigs[i].accumRedSize = 16;
pConfigs[i].accumGreenSize = 16;
pConfigs[i].accumBlueSize = 16;
pConfigs[i].accumAlphaSize = 0;
} else {
pConfigs[i].accumRedSize = 0;
pConfigs[i].accumGreenSize = 0;
pConfigs[i].accumBlueSize = 0;
pConfigs[i].accumAlphaSize = 0;
}
if (db)
pConfigs[i].doubleBuffer = TRUE;
else
pConfigs[i].doubleBuffer = FALSE;
pConfigs[i].stereo = FALSE;
pConfigs[i].bufferSize = 16;
pConfigs[i].depthSize = 16;
if (stencil)
pConfigs[i].stencilSize = 8;
else
pConfigs[i].stencilSize = 0;
pConfigs[i].auxBuffers = 0;
pConfigs[i].level = 0;
if (accum) {
pConfigs[i].visualRating = GLX_SLOW_CONFIG;
} else {
pConfigs[i].visualRating = GLX_NONE;
}
pConfigs[i].transparentPixel = GLX_NONE;
pConfigs[i].transparentRed = 0;
pConfigs[i].transparentGreen = 0;
pConfigs[i].transparentBlue = 0;
pConfigs[i].transparentAlpha = 0;
pConfigs[i].transparentIndex = 0;
i++;
}
}
}
break;
case 32:
numConfigs = 1;
if (RADEON_USE_ACCUM) numConfigs *= 2;
if (RADEON_USE_STENCIL) numConfigs *= 2;
if (use_db) numConfigs *= 2;
if (!(pConfigs
= (__GLXvisualConfig *)xcalloc(sizeof(__GLXvisualConfig),
numConfigs))) {
return FALSE;
}
if (!(pRADEONConfigs
= (RADEONConfigPrivPtr)xcalloc(sizeof(RADEONConfigPrivRec),
numConfigs))) {
xfree(pConfigs);
return FALSE;
}
if (!(pRADEONConfigPtrs
= (RADEONConfigPrivPtr *)xcalloc(sizeof(RADEONConfigPrivPtr),
numConfigs))) {
xfree(pConfigs);
xfree(pRADEONConfigs);
return FALSE;
}
i = 0;
for (db = 0; db <= use_db; db++) {
for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) {
for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) {
pRADEONConfigPtrs[i] = &pRADEONConfigs[i];
pConfigs[i].vid = (VisualID)(-1);
pConfigs[i].class = -1;
pConfigs[i].rgba = TRUE;
pConfigs[i].redSize = 8;
pConfigs[i].greenSize = 8;
pConfigs[i].blueSize = 8;
pConfigs[i].alphaSize = 8;
pConfigs[i].redMask = 0x00FF0000;
pConfigs[i].greenMask = 0x0000FF00;
pConfigs[i].blueMask = 0x000000FF;
pConfigs[i].alphaMask = 0xFF000000;
if (accum) {
pConfigs[i].accumRedSize = 16;
pConfigs[i].accumGreenSize = 16;
pConfigs[i].accumBlueSize = 16;
pConfigs[i].accumAlphaSize = 16;
} else {
pConfigs[i].accumRedSize = 0;
pConfigs[i].accumGreenSize = 0;
pConfigs[i].accumBlueSize = 0;
pConfigs[i].accumAlphaSize = 0;
}
if (db)
pConfigs[i].doubleBuffer = TRUE;
else
pConfigs[i].doubleBuffer = FALSE;
pConfigs[i].stereo = FALSE;
pConfigs[i].bufferSize = 32;
if (stencil) {
pConfigs[i].depthSize = 24;
pConfigs[i].stencilSize = 8;
} else {
pConfigs[i].depthSize = 24;
pConfigs[i].stencilSize = 0;
}
pConfigs[i].auxBuffers = 0;
pConfigs[i].level = 0;
if (accum) {
pConfigs[i].visualRating = GLX_SLOW_CONFIG;
} else {
pConfigs[i].visualRating = GLX_NONE;
}
pConfigs[i].transparentPixel = GLX_NONE;
pConfigs[i].transparentRed = 0;
pConfigs[i].transparentGreen = 0;
pConfigs[i].transparentBlue = 0;
pConfigs[i].transparentAlpha = 0;
pConfigs[i].transparentIndex = 0;
i++;
}
}
}
break;
}
info->numVisualConfigs = numConfigs;
info->pVisualConfigs = pConfigs;
info->pVisualConfigsPriv = pRADEONConfigs;
GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pRADEONConfigPtrs);
return TRUE;
}
static Bool RADEONCreateContext(ScreenPtr pScreen, VisualPtr visual,
drmContext hwContext, void *pVisualConfigPriv,
DRIContextType contextStore)
{
#ifdef PER_CONTEXT_SAREA
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONDRIContextPtr ctx_info;
ctx_info = (RADEONDRIContextPtr)contextStore;
if (!ctx_info) return FALSE;
if (drmAddMap(info->drmFD, 0,
info->perctx_sarea_size,
DRM_SHM,
DRM_REMOVABLE,
&ctx_info->sarea_handle) < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[dri] could not create private sarea for ctx id (%d)\n",
(int)hwContext);
return FALSE;
}
if (drmAddContextPrivateMapping(info->drmFD, hwContext,
ctx_info->sarea_handle) < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[dri] could not associate private sarea to ctx id (%d)\n",
(int)hwContext);
drmRmMap(info->drmFD, ctx_info->sarea_handle);
return FALSE;
}
ctx_info->ctx_id = hwContext;
#endif
return TRUE;
}
static void RADEONDestroyContext(ScreenPtr pScreen, drmContext hwContext,
DRIContextType contextStore)
{
#ifdef PER_CONTEXT_SAREA
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONDRIContextPtr ctx_info;
ctx_info = (RADEONDRIContextPtr)contextStore;
if (!ctx_info) return;
if (drmRmMap(info->drmFD, ctx_info->sarea_handle) < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[dri] could not remove private sarea for ctx id (%d)\n",
(int)hwContext);
}
#endif
}
static void RADEONEnterServer(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
if (info->accel) info->accel->NeedToSync = TRUE;
}
static void RADEONLeaveServer(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
RING_LOCALS;
if (info->CPInUse) {
RADEON_FLUSH_CACHE();
RADEON_WAIT_UNTIL_IDLE();
RADEONCPReleaseIndirect(pScrn);
info->CPInUse = FALSE;
}
}
static void RADEONDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
DRIContextType oldContextType,
void *oldContext,
DRIContextType newContextType,
void *newContext)
{
if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
(newContextType==DRI_2D_CONTEXT)) {
RADEONEnterServer(pScreen);
}
if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
(newContextType==DRI_2D_CONTEXT)) {
RADEONLeaveServer(pScreen);
}
}
static CARD32 radeon_mba_z16(RADEONInfoPtr info, int x, int y)
{
CARD32 pitch = info->frontPitch;
CARD32 address = 0;
CARD32 ba;
ba = (y / 16) * (pitch / 32) + (x / 32);
address |= (x & 0x7) << 1;
address |= (y & 0x7) << 4;
address |= (x & 0x8) << 4;
address |= (ba & 0x3) << 8;
address |= (y & 0x8) << 7;
address |= ((x & 0x10) ^ (y & 0x10)) << 7;
address |= (ba & ~0x3u) << 10;
return address;
}
static CARD32 radeon_mba_z32(RADEONInfoPtr info, int x, int y)
{
CARD32 pitch = info->frontPitch;
CARD32 address = 0;
CARD32 ba;
ba = (y / 16) * (pitch / 16) + (x / 16);
address |= (x & 0x7) << 2;
address |= (y & 0x3) << 5;
address |=
(((x & 0x10) >> 2) ^ (y & 0x4)) << 5;
address |= (ba & 0x3) << 8;
address |= (y & 0x8) << 7;
address |=
(((x & 0x8) << 1) ^ (y & 0x10)) << 7;
address |= (ba & ~0x3u) << 10;
return address;
}
#define WRITE_DEPTH16(_x, _y, d) \
*(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y))) = (d)
#define READ_DEPTH16(d, _x, _y) \
(d) = *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y)))
#define WRITE_DEPTH32(_x, _y, d) \
do { \
CARD32 tmp = \
*(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))); \
tmp &= 0xff000000; \
tmp |= ((d) & 0x00ffffff); \
*(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) = tmp; \
} while (0)
#define READ_DEPTH32(d, _x, _y) \
d = (*(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) \
& 0x00ffffff)
static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn,
int xa, int ya,
int xb, int yb,
int w, int h)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *buf = info->FB + info->depthOffset;
int xstart, xend, xdir;
int ystart, yend, ydir;
int x, y, d;
if (xa < xb) xdir = -1, xstart = w-1, xend = 0;
else xdir = 1, xstart = 0, xend = w-1;
if (ya < yb) ydir = -1, ystart = h-1, yend = 0;
else ydir = 1, ystart = 0, yend = h-1;
switch (pScrn->bitsPerPixel) {
case 16:
for (x = xstart; x != xend; x += xdir) {
for (y = ystart; y != yend; y += ydir) {
READ_DEPTH16(d, xa+x, ya+y);
WRITE_DEPTH16(xb+x, yb+y, d);
}
}
break;
case 32:
for (x = xstart; x != xend; x += xdir) {
for (y = ystart; y != yend; y += ydir) {
READ_DEPTH32(d, xa+x, ya+y);
WRITE_DEPTH32(xb+x, yb+y, d);
}
}
break;
default:
break;
}
}
static void RADEONDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
{
}
static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
RegionPtr prgnSrc, CARD32 indx)
{
ScreenPtr pScreen = pParent->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
BoxPtr pboxTmp, pboxNext, pboxBase;
DDXPointPtr pptTmp;
int xdir, ydir;
int screenwidth = pScrn->virtualX;
int screenheight = pScrn->virtualY;
BoxPtr pbox = REGION_RECTS(prgnSrc);
int nbox = REGION_NUM_RECTS(prgnSrc);
BoxPtr pboxNew1 = NULL;
BoxPtr pboxNew2 = NULL;
DDXPointPtr pptNew1 = NULL;
DDXPointPtr pptNew2 = NULL;
DDXPointPtr pptSrc = &ptOldOrg;
int dx = pParent->drawable.x - ptOldOrg.x;
int dy = pParent->drawable.y - ptOldOrg.y;
if (dy > 0) {
ydir = -1;
if (nbox > 1) {
pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
if (!pboxNew1) return;
pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
if (!pptNew1) {
DEALLOCATE_LOCAL(pboxNew1);
return;
}
pboxBase = pboxNext = pbox+nbox-1;
while (pboxBase >= pbox) {
while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
pboxNext--;
pboxTmp = pboxNext+1;
pptTmp = pptSrc + (pboxTmp - pbox);
while (pboxTmp <= pboxBase) {
*pboxNew1++ = *pboxTmp++;
*pptNew1++ = *pptTmp++;
}
pboxBase = pboxNext;
}
pboxNew1 -= nbox;
pbox = pboxNew1;
pptNew1 -= nbox;
pptSrc = pptNew1;
}
} else {
ydir = 1;
}
if (dx > 0) {
xdir = -1;
if (nbox > 1) {
pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
if (!pboxNew2 || !pptNew2) {
DEALLOCATE_LOCAL(pptNew2);
DEALLOCATE_LOCAL(pboxNew2);
DEALLOCATE_LOCAL(pptNew1);
DEALLOCATE_LOCAL(pboxNew1);
return;
}
pboxBase = pboxNext = pbox;
while (pboxBase < pbox+nbox) {
while ((pboxNext < pbox+nbox)
&& (pboxNext->y1 == pboxBase->y1))
pboxNext++;
pboxTmp = pboxNext;
pptTmp = pptSrc + (pboxTmp - pbox);
while (pboxTmp != pboxBase) {
*pboxNew2++ = *--pboxTmp;
*pptNew2++ = *--pptTmp;
}
pboxBase = pboxNext;
}
pboxNew2 -= nbox;
pbox = pboxNew2;
pptNew2 -= nbox;
pptSrc = pptNew2;
}
} else {
xdir = 1;
}
(*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy,
(CARD32)(-1), -1);
for (; nbox-- ; pbox++) {
int xa = pbox->x1;
int ya = pbox->y1;
int destx = xa + dx;
int desty = ya + dy;
int w = pbox->x2 - xa + 1;
int h = pbox->y2 - ya + 1;
if (destx < 0) xa -= destx, w += destx, destx = 0;
if (desty < 0) ya -= desty, h += desty, desty = 0;
if (destx + w > screenwidth) w = screenwidth - destx;
if (desty + h > screenheight) h = screenheight - desty;
if (w <= 0) continue;
if (h <= 0) continue;
RADEONSelectBuffer(pScrn, RADEON_BACK);
(*info->accel->SubsequentScreenToScreenCopy)(pScrn,
xa, ya,
destx, desty,
w, h);
if (info->depthMoves) {
RADEONSelectBuffer(pScrn, RADEON_DEPTH);
RADEONScreenToScreenCopyDepth(pScrn,
xa, ya,
destx, desty,
w, h);
}
}
RADEONSelectBuffer(pScrn, RADEON_FRONT);
DEALLOCATE_LOCAL(pptNew2);
DEALLOCATE_LOCAL(pboxNew2);
DEALLOCATE_LOCAL(pptNew1);
DEALLOCATE_LOCAL(pboxNew1);
info->accel->NeedToSync = TRUE;
}
static void RADEONDRIInitGARTValues(RADEONInfoPtr info)
{
int s, l;
info->gartOffset = 0;
info->ringStart = info->gartOffset;
info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1;
info->ringReadOffset = info->ringStart + info->ringMapSize;
info->ringReadMapSize = DRM_PAGE_SIZE;
info->bufStart = info->ringReadOffset + info->ringReadMapSize;
info->bufMapSize = info->bufSize*1024*1024;
info->gartTexStart = info->bufStart + info->bufMapSize;
s = (info->gartSize*1024*1024 - info->gartTexStart);
l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
info->gartTexMapSize = (s >> l) << l;
info->log2GARTTexGran = l;
}
static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen)
{
unsigned char *RADEONMMIO = info->MMIO;
unsigned long mode = drmAgpGetMode(info->drmFD);
unsigned int vendor = drmAgpVendorId(info->drmFD);
unsigned int device = drmAgpDeviceId(info->drmFD);
mode &= ~RADEON_AGP_MODE_MASK;
switch (info->agpMode) {
case 4: mode |= RADEON_AGP_4X_MODE;
case 2: mode |= RADEON_AGP_2X_MODE;
case 1: default: mode |= RADEON_AGP_1X_MODE;
}
if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE;
if ((vendor == PCI_VENDOR_AMD) &&
(device == PCI_CHIP_AMD761)) {
mode &= ~0x10;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
mode, vendor, device,
info->PciInfo->vendor,
info->PciInfo->chipType);
if (drmAgpEnable(info->drmFD, mode) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
drmAgpRelease(info->drmFD);
return FALSE;
}
if (info->ChipFamily < CHIP_FAMILY_R200)
OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000);
return TRUE;
}
static void RADEONSetAgpBase(RADEONInfoPtr info)
{
unsigned char *RADEONMMIO = info->MMIO;
OUTREG(RADEON_AGP_BASE, drmAgpBase(info->drmFD));
}
static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
{
int ret;
if (drmAgpAcquire(info->drmFD) < 0) {
xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n");
return FALSE;
}
if (!RADEONSetAgpMode(info, pScreen))
return FALSE;
RADEONDRIInitGARTValues(info);
if ((ret = drmAgpAlloc(info->drmFD, info->gartSize*1024*1024, 0, NULL,
&info->agpMemHandle)) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
drmAgpRelease(info->drmFD);
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] %d kB allocated with handle 0x%08lx\n",
info->gartSize*1024, info->agpMemHandle);
if (drmAgpBind(info->drmFD,
info->agpMemHandle, info->gartOffset) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n");
drmAgpFree(info->drmFD, info->agpMemHandle);
drmAgpRelease(info->drmFD);
return FALSE;
}
if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add ring mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] ring handle = 0x%08lx\n", info->ringHandle);
if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
(drmAddressPtr)&info->ring) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Ring mapped at 0x%08lx\n",
(unsigned long)info->ring);
if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add ring read ptr mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] ring read ptr handle = 0x%08lx\n",
info->ringReadPtrHandle);
if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
(drmAddressPtr)&info->ringReadPtr) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not map ring read ptr\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Ring read ptr mapped at 0x%08lx\n",
(unsigned long)info->ringReadPtr);
if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
DRM_AGP, 0, &info->bufHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add vertex/indirect buffers mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] vertex/indirect buffers handle = 0x%08lx\n",
info->bufHandle);
if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
(drmAddressPtr)&info->buf) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not map vertex/indirect buffers\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
(unsigned long)info->buf);
if (drmAddMap(info->drmFD, info->gartTexStart, info->gartTexMapSize,
DRM_AGP, 0, &info->gartTexHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add GART texture map mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] GART texture map handle = 0x%08lx\n",
info->gartTexHandle);
if (drmMap(info->drmFD, info->gartTexHandle, info->gartTexMapSize,
(drmAddressPtr)&info->gartTex) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not map GART texture map\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] GART Texture map mapped at 0x%08lx\n",
(unsigned long)info->gartTex);
RADEONSetAgpBase(info);
return TRUE;
}
static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen)
{
int ret;
int flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
ret = drmScatterGatherAlloc(info->drmFD, info->gartSize*1024*1024,
&info->pciMemHandle);
if (ret < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret);
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] %d kB allocated with handle 0x%08lx\n",
info->gartSize*1024, info->pciMemHandle);
RADEONDRIInitGARTValues(info);
if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not add ring mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] ring handle = 0x%08lx\n", info->ringHandle);
if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
(drmAddressPtr)&info->ring) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring mapped at 0x%08lx\n",
(unsigned long)info->ring);
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring contents 0x%08lx\n",
*(unsigned long *)(pointer)info->ring);
if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not add ring read ptr mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] ring read ptr handle = 0x%08lx\n",
info->ringReadPtrHandle);
if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
(drmAddressPtr)&info->ringReadPtr) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not map ring read ptr\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring read ptr mapped at 0x%08lx\n",
(unsigned long)info->ringReadPtr);
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring read ptr contents 0x%08lx\n",
*(unsigned long *)(pointer)info->ringReadPtr);
if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not add vertex/indirect buffers mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] vertex/indirect buffers handle = 0x%08lx\n",
info->bufHandle);
if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
(drmAddressPtr)&info->buf) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not map vertex/indirect buffers\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
(unsigned long)info->buf);
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Vertex/indirect buffers contents 0x%08lx\n",
*(unsigned long *)(pointer)info->buf);
if (drmAddMap(info->drmFD, info->gartTexStart, info->gartTexMapSize,
DRM_SCATTER_GATHER, 0, &info->gartTexHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not add GART texture map mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] GART texture map handle = 0x%08lx\n",
info->gartTexHandle);
if (drmMap(info->drmFD, info->gartTexHandle, info->gartTexMapSize,
(drmAddressPtr)&info->gartTex) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not map GART texture map\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] GART Texture map mapped at 0x%08lx\n",
(unsigned long)info->gartTex);
return TRUE;
}
static Bool RADEONDRIMapInit(RADEONInfoPtr info, ScreenPtr pScreen)
{
info->registerSize = RADEON_MMIOSIZE;
if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize,
DRM_REGISTERS, DRM_READ_ONLY, &info->registerHandle) < 0) {
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] register handle = 0x%08lx\n", info->registerHandle);
return TRUE;
}
static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
int cpp = info->CurrentLayout.pixel_bytes;
drmRadeonInit drmInfo;
memset(&drmInfo, 0, sizeof(drmRadeonInit));
if ((info->ChipFamily == CHIP_FAMILY_R200) ||
(info->ChipFamily == CHIP_FAMILY_RV250) ||
(info->ChipFamily == CHIP_FAMILY_RV280) )
drmInfo.func = DRM_RADEON_INIT_R200_CP;
else
drmInfo.func = DRM_RADEON_INIT_CP;
drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec);
drmInfo.is_pci = info->IsPCI;
drmInfo.cp_mode = info->CPMode;
drmInfo.gart_size = info->gartSize*1024*1024;
drmInfo.ring_size = info->ringSize*1024*1024;
drmInfo.usec_timeout = info->CPusecTimeout;
drmInfo.fb_bpp = info->CurrentLayout.pixel_code;
drmInfo.depth_bpp = info->CurrentLayout.pixel_code;
drmInfo.front_offset = info->frontOffset;
drmInfo.front_pitch = info->frontPitch * cpp;
drmInfo.back_offset = info->backOffset;
drmInfo.back_pitch = info->backPitch * cpp;
drmInfo.depth_offset = info->depthOffset;
drmInfo.depth_pitch = info->depthPitch * cpp;
drmInfo.fb_offset = info->fbHandle;
drmInfo.mmio_offset = info->registerHandle;
drmInfo.ring_offset = info->ringHandle;
drmInfo.ring_rptr_offset = info->ringReadPtrHandle;
drmInfo.buffers_offset = info->bufHandle;
drmInfo.gart_textures_offset= info->gartTexHandle;
if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT,
&drmInfo, sizeof(drmRadeonInit)) < 0)
return FALSE;
RADEONEngineRestore(pScrn);
return TRUE;
}
static void RADEONDRIGartHeapInit(RADEONInfoPtr info, ScreenPtr pScreen)
{
drmRadeonMemInitHeap drmHeap;
if (info->drmMinor >= 6) {
drmHeap.region = RADEON_MEM_REGION_GART;
drmHeap.start = 0;
drmHeap.size = info->gartTexMapSize;
if (drmCommandWrite(info->drmFD, DRM_RADEON_INIT_HEAP,
&drmHeap, sizeof(drmHeap))) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[drm] Failed to initialize GART heap manager\n");
} else {
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] Initialized kernel GART heap manager, %d\n",
info->gartTexMapSize);
}
} else {
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] Kernel module too old (1.%d) for GART heap manager\n",
info->drmMinor);
}
}
static Bool RADEONDRIBufInit(RADEONInfoPtr info, ScreenPtr pScreen)
{
info->bufNumBufs = drmAddBufs(info->drmFD,
info->bufMapSize / RADEON_BUFFER_SIZE,
RADEON_BUFFER_SIZE,
info->IsPCI ? DRM_SG_BUFFER : DRM_AGP_BUFFER,
info->bufStart);
if (info->bufNumBufs <= 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[drm] Could not create vertex/indirect buffers list\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] Added %d %d byte vertex/indirect buffers\n",
info->bufNumBufs, RADEON_BUFFER_SIZE);
if (!(info->buffers = drmMapBufs(info->drmFD))) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[drm] Failed to map vertex/indirect buffers list\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] Mapped %d vertex/indirect buffers\n",
info->buffers->count);
return TRUE;
}
static void RADEONDRIIrqInit(RADEONInfoPtr info, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
if (!info->irq) {
info->irq = drmGetInterruptFromBusID(
info->drmFD,
((pciConfigPtr)info->PciInfo->thisCard)->busnum,
((pciConfigPtr)info->PciInfo->thisCard)->devnum,
((pciConfigPtr)info->PciInfo->thisCard)->funcnum);
if ((drmCtlInstHandler(info->drmFD, info->irq)) != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[drm] failure adding irq handler, "
"there is a device already using that irq\n"
"[drm] falling back to irq-free operation\n");
info->irq = 0;
} else {
unsigned char *RADEONMMIO = info->MMIO;
info->ModeReg.gen_int_cntl = INREG( RADEON_GEN_INT_CNTL );
}
}
if (info->irq)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[drm] dma control initialized, using IRQ %d\n",
info->irq);
}
static void RADEONDRICPInit(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
info->BusCntl &= ~RADEON_BUS_MASTER_DIS;
RADEONCP_START(pScrn, info);
RADEONSelectBuffer(pScrn, RADEON_FRONT);
}
Bool RADEONDRIScreenInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
DRIInfoPtr pDRIInfo;
RADEONDRIPtr pRADEONDRI;
int major, minor, patch;
drmVersionPtr version;
if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE;
if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE;
if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] RADEONDRIScreenInit failed (libdri.a too old)\n");
return FALSE;
}
DRIQueryVersion(&major, &minor, &patch);
if (major != 4 || minor < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] RADEONDRIScreenInit failed because of a version "
"mismatch.\n"
"[dri] libDRI version is %d.%d.%d but version 4.0.x is "
"needed.\n"
"[dri] Disabling DRI.\n",
major, minor, patch);
return FALSE;
}
switch (info->CurrentLayout.pixel_code) {
case 8:
case 15:
case 24:
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] RADEONInitVisualConfigs failed "
"(depth %d not supported). "
"Disabling DRI.\n", info->CurrentLayout.pixel_code);
return FALSE;
case 16:
case 32:
break;
}
if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
info->pDRIInfo = pDRIInfo;
pDRIInfo->drmDriverName = RADEON_DRIVER_NAME;
if ( (info->ChipFamily == CHIP_FAMILY_R200) ||
(info->ChipFamily == CHIP_FAMILY_RV250) ||
(info->ChipFamily == CHIP_FAMILY_RV280) )
pDRIInfo->clientDriverName = R200_DRIVER_NAME;
else
pDRIInfo->clientDriverName = RADEON_DRIVER_NAME;
pDRIInfo->busIdString = xalloc(64);
sprintf(pDRIInfo->busIdString,
"PCI:%d:%d:%d",
info->PciInfo->bus,
info->PciInfo->device,
info->PciInfo->func);
pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR;
pDRIInfo->ddxDriverMinorVersion = RADEON_VERSION_MINOR;
pDRIInfo->ddxDriverPatchVersion = RADEON_VERSION_PATCH;
pDRIInfo->frameBufferPhysicalAddress = info->LinearAddr;
pDRIInfo->frameBufferSize = info->FbMapSize;
pDRIInfo->frameBufferStride = (pScrn->displayWidth *
info->CurrentLayout.pixel_bytes);
pDRIInfo->ddxDrawableTableEntry = RADEON_MAX_DRAWABLES;
pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES
< RADEON_MAX_DRAWABLES
? SAREA_MAX_DRAWABLES
: RADEON_MAX_DRAWABLES);
#ifdef PER_CONTEXT_SAREA
info->perctx_sarea_size = 64 * 1024;
#endif
#ifdef NOT_DONE
pDRIInfo->SAREASize = ((sizeof(XF86DRISAREARec) + 0xfff)
& 0x1000);
#else
if (sizeof(XF86DRISAREARec)+sizeof(RADEONSAREAPriv) > SAREA_MAX) {
ErrorF("Data does not fit in SAREA\n");
return FALSE;
}
pDRIInfo->SAREASize = SAREA_MAX;
#endif
if (!(pRADEONDRI = (RADEONDRIPtr)xcalloc(sizeof(RADEONDRIRec),1))) {
DRIDestroyInfoRec(info->pDRIInfo);
info->pDRIInfo = NULL;
return FALSE;
}
pDRIInfo->devPrivate = pRADEONDRI;
pDRIInfo->devPrivateSize = sizeof(RADEONDRIRec);
pDRIInfo->contextSize = sizeof(RADEONDRIContextRec);
pDRIInfo->CreateContext = RADEONCreateContext;
pDRIInfo->DestroyContext = RADEONDestroyContext;
pDRIInfo->SwapContext = RADEONDRISwapContext;
pDRIInfo->InitBuffers = RADEONDRIInitBuffers;
pDRIInfo->MoveBuffers = RADEONDRIMoveBuffers;
pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
pDRIInfo->OpenFullScreen = RADEONDRIOpenFullScreen;
pDRIInfo->CloseFullScreen = RADEONDRICloseFullScreen;
pDRIInfo->TransitionTo2d = RADEONDRITransitionTo2d;
pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d;
pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d;
pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d;
pDRIInfo->createDummyCtx = TRUE;
pDRIInfo->createDummyCtxPriv = FALSE;
if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] DRIScreenInit failed. Disabling DRI.\n");
xfree(pDRIInfo->devPrivate);
pDRIInfo->devPrivate = NULL;
DRIDestroyInfoRec(pDRIInfo);
pDRIInfo = NULL;
return FALSE;
}
if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
version = drmGetLibVersion(info->drmFD);
} else {
version = drmGetVersion(info->drmFD);
version->version_major = 1;
version->version_minor = 0;
version->version_patchlevel = 0;
}
if (version) {
if (version->version_major != 1 ||
version->version_minor < 1) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] RADEONDRIScreenInit failed because of a "
"version mismatch.\n"
"[dri] libdrm.a module version is %d.%d.%d but "
"version 1.1.x is needed.\n"
"[dri] Disabling DRI.\n",
version->version_major,
version->version_minor,
version->version_patchlevel);
drmFreeVersion(version);
RADEONDRICloseScreen(pScreen);
return FALSE;
}
drmFreeVersion(version);
}
version = drmGetVersion(info->drmFD);
if (version) {
int req_minor, req_patch;
if ((info->ChipFamily == CHIP_FAMILY_R200) ||
(info->ChipFamily == CHIP_FAMILY_RV250) ||
(info->ChipFamily == CHIP_FAMILY_RV280)) {
req_minor = 5;
req_patch = 0;
} else {
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
req_minor = 1;
req_patch = 0;
#else
req_minor = 2;
req_patch = 1;
#endif
}
if (version->version_major != 1 ||
version->version_minor < req_minor ||
(version->version_minor == req_minor &&
version->version_patchlevel < req_patch)) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] RADEONDRIScreenInit failed because of a version "
"mismatch.\n"
"[dri] radeon.o kernel module version is %d.%d.%d "
"but version 1.%d.%d or newer is needed.\n"
"[dri] Disabling DRI.\n",
version->version_major,
version->version_minor,
version->version_patchlevel,
req_minor,
req_patch);
drmFreeVersion(version);
RADEONDRICloseScreen(pScreen);
return FALSE;
}
if (version->version_minor < 3) {
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[dri] Some DRI features disabled because of version "
"mismatch.\n"
"[dri] radeon.o kernel module version is %d.%d.%d but "
"1.3.1 or later is preferred.\n",
version->version_major,
version->version_minor,
version->version_patchlevel);
}
info->drmMinor = version->version_minor;
drmFreeVersion(version);
}
if (!info->IsPCI && !RADEONDRIAgpInit(info, pScreen)) {
#if defined(__alpha__) || defined(__powerpc__)
info->IsPCI = TRUE;
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[agp] AGP failed to initialize "
"-- falling back to PCI mode.\n");
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[agp] If this is an AGP card, you may want to make sure "
"the agpgart\nkernel module is loaded before the radeon "
"kernel module.\n");
#else
RADEONDRICloseScreen(pScreen);
return FALSE;
#endif
}
if (info->IsPCI && !RADEONDRIPciInit(info, pScreen)) {
RADEONDRICloseScreen(pScreen);
return FALSE;
}
if (!RADEONDRIMapInit(info, pScreen)) {
RADEONDRICloseScreen(pScreen);
return FALSE;
}
{
void *scratch_ptr;
int scratch_int;
DRIGetDeviceInfo(pScreen, &info->fbHandle,
&scratch_int, &scratch_int,
&scratch_int, &scratch_int,
&scratch_ptr);
}
if (!RADEONInitVisualConfigs(pScreen)) {
RADEONDRICloseScreen(pScreen);
return FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
return TRUE;
}
Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONSAREAPrivPtr pSAREAPriv;
RADEONDRIPtr pRADEONDRI;
info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
if (!DRIFinishScreenInit(pScreen)) {
RADEONDRICloseScreen(pScreen);
return FALSE;
}
if (!RADEONDRIKernelInit(info, pScreen)) {
RADEONDRICloseScreen(pScreen);
return FALSE;
}
if (!RADEONDRIBufInit(info, pScreen)) {
RADEONDRICloseScreen(pScreen);
return FALSE;
}
RADEONDRIIrqInit(info, pScreen);
RADEONDRIGartHeapInit(info, pScreen);
RADEONDRICPInit(pScrn);
pSAREAPriv = (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
pRADEONDRI = (RADEONDRIPtr)info->pDRIInfo->devPrivate;
pRADEONDRI->deviceID = info->Chipset;
pRADEONDRI->width = pScrn->virtualX;
pRADEONDRI->height = pScrn->virtualY;
pRADEONDRI->depth = pScrn->depth;
pRADEONDRI->bpp = pScrn->bitsPerPixel;
pRADEONDRI->IsPCI = info->IsPCI;
pRADEONDRI->AGPMode = info->agpMode;
pRADEONDRI->frontOffset = info->frontOffset;
pRADEONDRI->frontPitch = info->frontPitch;
pRADEONDRI->backOffset = info->backOffset;
pRADEONDRI->backPitch = info->backPitch;
pRADEONDRI->depthOffset = info->depthOffset;
pRADEONDRI->depthPitch = info->depthPitch;
pRADEONDRI->textureOffset = info->textureOffset;
pRADEONDRI->textureSize = info->textureSize;
pRADEONDRI->log2TexGran = info->log2TexGran;
pRADEONDRI->registerHandle = info->registerHandle;
pRADEONDRI->registerSize = info->registerSize;
pRADEONDRI->statusHandle = info->ringReadPtrHandle;
pRADEONDRI->statusSize = info->ringReadMapSize;
pRADEONDRI->gartTexHandle = info->gartTexHandle;
pRADEONDRI->gartTexMapSize = info->gartTexMapSize;
pRADEONDRI->log2GARTTexGran = info->log2GARTTexGran;
pRADEONDRI->gartTexOffset = info->gartTexStart;
pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
#ifdef PER_CONTEXT_SAREA
pRADEONDRI->perctx_sarea_size = info->perctx_sarea_size;
#endif
if (info->allowPageFlip ) {
ShadowFBInit( pScreen, RADEONDRIRefreshArea );
} else {
info->allowPageFlip = 0;
}
return TRUE;
}
void RADEONDRIResume(ScreenPtr pScreen)
{
int _ret;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
if (info->drmMinor >= 9) {
xf86DrvMsg(pScreen->myNum, X_INFO,
"[RESUME] Attempting to re-init Radeon hardware.\n");
} else {
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[RESUME] Cannot re-init Radeon hardware, DRM too old\n"
"(need 1.9.0 or newer)\n");
return;
}
if (!info->IsPCI) {
if (!RADEONSetAgpMode(info, pScreen))
return;
RADEONSetAgpBase(info);
}
_ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_RESUME);
if (_ret) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"%s: CP resume %d\n", __FUNCTION__, _ret);
}
RADEONEngineRestore(pScrn);
RADEONDRICPInit(pScrn);
}
void RADEONDRICloseScreen(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
drmRadeonInit drmInfo;
RING_LOCALS;
if (info->directRenderingEnabled) {
if (info->CPInUse) {
RADEON_FLUSH_CACHE();
RADEON_WAIT_UNTIL_IDLE();
RADEONCPReleaseIndirect(pScrn);
info->CPInUse = FALSE;
}
RADEONCP_STOP(pScrn, info);
}
if (info->irq) {
drmCtlUninstHandler(info->drmFD);
info->irq = 0;
info->ModeReg.gen_int_cntl = 0;
}
if (info->buffers) {
drmUnmapBufs(info->buffers);
info->buffers = NULL;
}
memset(&drmInfo, 0, sizeof(drmRadeonInit));
drmInfo.func = DRM_RADEON_CLEANUP_CP;
drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT,
&drmInfo, sizeof(drmRadeonInit));
if (info->gartTex) {
drmUnmap(info->gartTex, info->gartTexMapSize);
info->gartTex = NULL;
}
if (info->buf) {
drmUnmap(info->buf, info->bufMapSize);
info->buf = NULL;
}
if (info->ringReadPtr) {
drmUnmap(info->ringReadPtr, info->ringReadMapSize);
info->ringReadPtr = NULL;
}
if (info->ring) {
drmUnmap(info->ring, info->ringMapSize);
info->ring = NULL;
}
if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
drmAgpUnbind(info->drmFD, info->agpMemHandle);
drmAgpFree(info->drmFD, info->agpMemHandle);
info->agpMemHandle = DRM_AGP_NO_HANDLE;
drmAgpRelease(info->drmFD);
}
if (info->pciMemHandle) {
drmScatterGatherFree(info->drmFD, info->pciMemHandle);
info->pciMemHandle = 0;
}
DRICloseScreen(pScreen);
if (info->pDRIInfo) {
if (info->pDRIInfo->devPrivate) {
xfree(info->pDRIInfo->devPrivate);
info->pDRIInfo->devPrivate = NULL;
}
DRIDestroyInfoRec(info->pDRIInfo);
info->pDRIInfo = NULL;
}
if (info->pVisualConfigs) {
xfree(info->pVisualConfigs);
info->pVisualConfigs = NULL;
}
if (info->pVisualConfigsPriv) {
xfree(info->pVisualConfigsPriv);
info->pVisualConfigsPriv = NULL;
}
}
static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen)
{
return TRUE;
}
static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen)
{
return TRUE;
}
static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
int i;
RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0)
return;
(*info->accel->SetupForScreenToScreenCopy)(pScrn,
1, 1, GXcopy,
(CARD32)(-1), -1);
for (i = 0 ; i < num ; i++, pbox++) {
int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1);
int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1);
if (xa <= xb && ya <= yb) {
(*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya,
xa + info->backX,
ya + info->backY,
xb - xa + 1,
yb - ya + 1);
}
}
}
static void RADEONEnablePageFlip(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
if (info->allowPageFlip) {
(*info->accel->SetupForScreenToScreenCopy)(pScrn,
1, 1, GXcopy,
(CARD32)(-1), -1);
(*info->accel->SubsequentScreenToScreenCopy)(pScrn,
0,
0,
info->backX,
info->backY,
pScrn->virtualX,
pScrn->virtualY);
pSAREAPriv->pfAllowPageFlip = 1;
}
}
static void RADEONDisablePageFlip(ScreenPtr pScreen)
{
RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
pSAREAPriv->pfAllowPageFlip = 0;
}
static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen)
{
RADEONDisablePageFlip(pScreen);
}
static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen)
{
RADEONEnablePageFlip(pScreen);
}
static void RADEONDRITransitionTo3d(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
FBAreaPtr fbarea;
int width, height;
if (info->backArea) {
xf86FreeOffscreenArea(info->backArea);
info->backArea = NULL;
}
xf86PurgeUnlockedOffscreenAreas(pScreen);
xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
if (height < (info->depthTexLines + info->backLines)) {
xf86FreeOffscreenLinear(info->videoLinear);
info->videoLinear = NULL;
xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
}
fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
height
- info->depthTexLines
- info->backLines,
pScrn->displayWidth,
NULL, NULL, NULL);
if (!fbarea)
xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder "
"offscreen area, you might experience screen corruption\n");
info->backArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
info->backLines,
pScrn->displayWidth,
NULL, NULL, NULL);
if (!info->backArea)
xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen "
"area for back buffer, you might experience screen "
"corruption\n");
info->depthTexArea = xf86AllocateOffscreenArea(pScreen,
pScrn->displayWidth,
info->depthTexLines,
pScrn->displayWidth,
NULL, NULL, NULL);
if (!info->depthTexArea)
xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen "
"area for depth buffer and textures, you might "
"experience screen corruption\n");
xf86FreeOffscreenArea(fbarea);
RADEONEnablePageFlip(pScreen);
info->have3DWindows = 1;
if (info->cursor_start)
xf86ForceHWCursor (pScreen, TRUE);
}
static void RADEONDRITransitionTo2d(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
if (pSAREAPriv->pfCurrentPage == 0) {
RADEONDisablePageFlip(pScreen);
xf86FreeOffscreenArea(info->backArea);
info->backArea = NULL;
} else {
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[dri] RADEONDRITransitionTo2d: "
"kernel failed to unflip buffers.\n");
}
xf86FreeOffscreenArea(info->depthTexArea);
info->have3DWindows = 0;
if (info->cursor_start)
xf86ForceHWCursor (pScreen, FALSE);
}