diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2007-11-24 20:08:20 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2007-11-24 20:08:20 +0000 |
commit | 6a3b94f3d640fd972b5ec8b244a66c92c5ebec20 (patch) | |
tree | ba3dd1c53b25c79ae7efbfa26a0dd8fd2cbea9ab /driver/xf86-video-intel/src/i830_dri.c | |
parent | 621df55ad49646572010dd46760717472a2cf8f4 (diff) |
merge xf86-video-intel 2.2.0
Diffstat (limited to 'driver/xf86-video-intel/src/i830_dri.c')
-rw-r--r-- | driver/xf86-video-intel/src/i830_dri.c | 1038 |
1 files changed, 637 insertions, 401 deletions
diff --git a/driver/xf86-video-intel/src/i830_dri.c b/driver/xf86-video-intel/src/i830_dri.c index 56db194b4..b223b02e7 100644 --- a/driver/xf86-video-intel/src/i830_dri.c +++ b/driver/xf86-video-intel/src/i830_dri.c @@ -81,12 +81,26 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i830_dri.h" -#include "dristruct.h" +#include "i915_drm.h" + +/* This block and the corresponding configure test can be removed when + * libdrm >= 2.3.1 is required. + */ +#ifndef HAVE_I915_FLIP + +#define DRM_VBLANK_FLIP 0x8000000 + +typedef struct drm_i915_flip { + int pipes; +} drm_i915_flip_t; + +#undef DRM_IOCTL_I915_FLIP +#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \ + drm_i915_flip_t) -static char I830KernelDriverName[] = "i915"; -static char I830ClientDriverName[] = "i915tex"; -static char I965ClientDriverName[] = "i965"; -static char I830LegacyClientDriverName[] = "i915"; +#endif + +#include "dristruct.h" static Bool I830InitVisualConfigs(ScreenPtr pScreen); static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual, @@ -105,11 +119,24 @@ static void I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, static void I830DRITransitionTo2d(ScreenPtr pScreen); static void I830DRITransitionTo3d(ScreenPtr pScreen); +#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)) +#define DRI_SUPPORTS_CLIP_NOTIFY 1 +#else +#define DRI_SUPPORTS_CLIP_NOTIFY 0 static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen); static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen); +#endif -#if 0 -static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf); +#if (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 4)) +#define DRI_DRIVER_FRAMEBUFFER_MAP 1 +#else +#define DRI_DRIVER_FRAMEBUFFER_MAP 0 +#endif + +#ifdef DRI_SUPPORTS_CLIP_NOTIFY +static void I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num); #endif extern void GlxSetVisualConfigs(int nconfigs, @@ -145,22 +172,22 @@ I830InitDma(ScrnInfoPtr pScrn) memset(&info, 0, sizeof(drmI830Init)); info.func = I830_INIT_DMA; - info.ring_start = ring->mem.Start + pI830->LinearAddr; - info.ring_end = ring->mem.End + pI830->LinearAddr; - info.ring_size = ring->mem.Size; + info.ring_start = ring->mem->offset + pI830->LinearAddr; + info.ring_end = ring->mem->end + pI830->LinearAddr; + info.ring_size = ring->mem->size; info.mmio_offset = (unsigned int)pI830DRI->regs; info.sarea_priv_offset = sizeof(XF86DRISAREARec); - info.front_offset = pI830->FrontBuffer.Start; - info.back_offset = pI830->BackBuffer.Start; - info.depth_offset = pI830->DepthBuffer.Start; + info.front_offset = pI830->front_buffer->offset; + info.back_offset = pI830->back_buffer->offset; + info.depth_offset = pI830->depth_buffer->offset; info.w = pScrn->virtualX; info.h = pScrn->virtualY; - info.pitch = pI830->displayWidth; - info.back_pitch = pI830->displayWidth; - info.depth_pitch = pI830->displayWidth; + info.pitch = pScrn->displayWidth; + info.back_pitch = pScrn->displayWidth; + info.depth_pitch = pScrn->displayWidth; info.cpp = pI830->cpp; if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT, @@ -209,6 +236,22 @@ I830SetParam(ScrnInfoPtr pScrn, int param, int value) return TRUE; } +static Bool +I830SetHWS(ScrnInfoPtr pScrn, int addr) +{ + I830Ptr pI830 = I830PTR(pScrn); + drmI830HWS hws; + + hws.addr = addr; + + if (drmCommandWrite(pI830->drmSubFD, DRM_I830_HWS_PAGE_ADDR, + &hws, sizeof(drmI830HWS))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "G33 status page initialization Failed\n"); + return FALSE; + } + return TRUE; +} static Bool I830InitVisualConfigs(ScreenPtr pScreen) @@ -216,9 +259,9 @@ I830InitVisualConfigs(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); int numConfigs = 0; - __GLXvisualConfig *pConfigs = 0; - I830ConfigPrivPtr pI830Configs = 0; - I830ConfigPrivPtr *pI830ConfigPtrs = 0; + __GLXvisualConfig *pConfigs = NULL; + I830ConfigPrivPtr pI830Configs = NULL; + I830ConfigPrivPtr *pI830ConfigPtrs = NULL; int accum, stencil, db, depth; int i; @@ -426,15 +469,24 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn) /* Check that the GLX, DRI, and DRM modules have been loaded by testing * for known symbols in each module. */ - if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) + if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: glx not loaded\n", __FUNCTION__); return FALSE; - if (!xf86LoaderCheckSymbol("DRIScreenInit")) + } + if (!xf86LoaderCheckSymbol("DRIScreenInit")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: dri not loaded\n", __FUNCTION__); return FALSE; - if (!xf86LoaderCheckSymbol("drmAvailable")) + } + if (!xf86LoaderCheckSymbol("drmAvailable")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: libdrm not loaded\n", __FUNCTION__); return FALSE; + } if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[dri] %s failed (libdri.a too old)\n", "I830CheckDRIAvailable"); + "[dri] %s failed (libdri.a too old)\n", __FUNCTION__); return FALSE; } @@ -443,7 +495,8 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn) int major, minor, patch; DRIQueryVersion(&major, &minor, &patch); - if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { + if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION || + major < 5) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] %s failed because of a version mismatch.\n" "[dri] libDRI version is %d.%d.%d but version %d.%d.x is needed.\n" @@ -480,34 +533,30 @@ I830DRIScreenInit(ScreenPtr pScreen) pI830->pDRIInfo = pDRIInfo; pI830->LockHeld = 0; - pDRIInfo->drmDriverName = I830KernelDriverName; - if (IS_I96X(pI830)) - pDRIInfo->clientDriverName = I965ClientDriverName; - else - pDRIInfo->clientDriverName = I830ClientDriverName; + pDRIInfo->drmDriverName = "i915"; + if (IS_I965G(pI830)) + pDRIInfo->clientDriverName = "i965"; + else + pDRIInfo->clientDriverName = "i915"; if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { pDRIInfo->busIdString = DRICreatePCIBusID(pI830->PciInfo); } else { pDRIInfo->busIdString = xalloc(64); sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", +#if XSERVER_LIBPCIACCESS + ((pI830->PciInfo->domain << 8) | pI830->PciInfo->bus), + pI830->PciInfo->dev, pI830->PciInfo->func +#else ((pciConfigPtr) pI830->PciInfo->thisCard)->busnum, ((pciConfigPtr) pI830->PciInfo->thisCard)->devnum, - ((pciConfigPtr) pI830->PciInfo->thisCard)->funcnum); + ((pciConfigPtr) pI830->PciInfo->thisCard)->funcnum +#endif + ); } pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL; -#if 1 /* Remove this soon - see bug 5714 */ - pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr + - pI830->FrontBuffer.Start; - pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * - pScrn->virtualY * pI830->cpp); -#else - /* For rotation we map a 0 length framebuffer as we remap ourselves later */ - pDRIInfo->frameBufferSize = 0; -#endif - pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp; pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES; if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES) @@ -529,7 +578,7 @@ I830DRIScreenInit(ScreenPtr pScreen) if (!(pI830DRI = (I830DRIPtr) xcalloc(sizeof(I830DRIRec), 1))) { DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; return FALSE; } pDRIInfo->devPrivate = pI830DRI; @@ -542,42 +591,70 @@ I830DRIScreenInit(ScreenPtr pScreen) pDRIInfo->InitBuffers = I830DRIInitBuffers; pDRIInfo->MoveBuffers = I830DRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + +#if DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3) + if (pI830->useEXA) + pDRIInfo->texOffsetStart = I830TexOffsetStart; +#endif + +#if DRI_SUPPORTS_CLIP_NOTIFY + pDRIInfo->ClipNotify = I830DRIClipNotify; +#endif + +#if DRI_DRIVER_FRAMEBUFFER_MAP + /* DRI version is high enough that we can get the DRI code to not + * try to manage the framebuffer. + */ + pDRIInfo->frameBufferPhysicalAddress = 0; + pDRIInfo->frameBufferSize = 0; + pDRIInfo->frameBufferStride = 0; + pDRIInfo->dontMapFrameBuffer = TRUE; +#else + /* Supply a dummy mapping info required by DRI setup. + */ + pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr; + pDRIInfo->frameBufferSize = GTT_PAGE_SIZE; + pDRIInfo->frameBufferStride = 1; +#endif + pDRIInfo->TransitionTo2d = I830DRITransitionTo2d; pDRIInfo->TransitionTo3d = I830DRITransitionTo3d; + +#if !DRI_SUPPORTS_CLIP_NOTIFY pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d; pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d; +#endif /* do driver-independent DRI screen initialization here */ if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); xfree(pDRIInfo->devPrivate); - pDRIInfo->devPrivate = 0; + pDRIInfo->devPrivate = NULL; DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; return FALSE; } -#if 0 /* disabled now, see frameBufferSize above being set to 0 */ - /* for this driver, get rid of the front buffer mapping now */ - if (xf86LoaderCheckSymbol("DRIGetScreenPrivate")) { - DRIScreenPrivPtr pDRIPriv - = (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen); - - if (pDRIPriv && pDRIPriv->drmFD && pDRIPriv->hFrameBuffer) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[intel] removing original screen mapping\n"); - drmRmMap(pDRIPriv->drmFD, pDRIPriv->hFrameBuffer); - pDRIPriv->hFrameBuffer = 0; - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[intel] done removing original screen mapping\n"); - } + /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */ + if (pDRIInfo->frameBufferSize != 0) { + int tmp; + drm_handle_t fb_handle; + void *ptmp; + + /* With the compat method, it will continue to report + * the wrong map out of GetDeviceInfo, which will break AIGLX. + */ + DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp); + drmRmMap(pI830->drmSubFD, fb_handle); + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Removed DRI frontbuffer mapping in compatibility mode.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRIGetDeviceInfo will report incorrect frontbuffer " + "handle.\n"); } - else { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[intel] DRIGetScreenPrivate not found!!!!\n"); - } -#endif /* Check the i915 DRM versioning */ { @@ -637,164 +714,67 @@ I830DRIScreenInit(ScreenPtr pScreen) drmFreeVersion(version); return FALSE; } - if (strncmp(version->name, I830KernelDriverName, strlen(I830KernelDriverName))) { - xf86DrvMsg(pScreen->myNum, X_WARNING, - "i830 Kernel module detected, Use the i915 Kernel module instead, aborting DRI init.\n"); + /* Check whether the kernel module attached to the device isn't the + * one we expected (meaning it's the old i830 module). + */ + if (strncmp(version->name, pDRIInfo->drmDriverName, + strlen(pDRIInfo->drmDriverName))) + { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "Detected i830 kernel module. The i915 kernel module " + "is required for DRI. Aborting.\n"); I830DRICloseScreen(pScreen); drmFreeVersion(version); return FALSE; } pI830->drmMinor = version->version_minor; - if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) { - if ((version->version_major > 1) || - ((version->version_minor >= 7) && - (version->version_major == 1))) { - pI830->mmModeFlags |= I830_KERNEL_MM; - } else { - pI830->mmModeFlags |= I830_KERNEL_TEX; - } - } else { - xf86DrvMsg(pScreen->myNum, X_INFO, - "Not enabling the DRM memory manager.\n"); - } +#ifdef DAMAGE + if (pI830->allowPageFlip && pI830->drmMinor < 9) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRM version 1.9 or newer required for Page flipping. " + "Disabling.\n"); + pI830->allowPageFlip = FALSE; + } +#endif drmFreeVersion(version); } } - /* - * Backwards compatibility - */ - - if ((pDRIInfo->clientDriverName == I830ClientDriverName) && - (pI830->mmModeFlags & I830_KERNEL_TEX)) { - pDRIInfo->clientDriverName = I830LegacyClientDriverName; - } - return TRUE; } -Bool -I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) -{ - ScreenPtr pScreen = pScrn->pScreen; - I830Ptr pI830 = I830PTR(pScrn); - -#if 1 /* Remove this soon - see bug 5714 */ - pI830->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * - pScrn->virtualY * pI830->cpp); -#endif - - /* The I965 isn't ready for the front buffer mapping to be moved around, - * because of issues with rmmap, it seems. - */ - if (!IS_I96X(pI830)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] Mapping front buffer\n"); - if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)(sarea->front_offset + pI830->LinearAddr), - sarea->front_size, - DRM_AGP, - 0, - (drmAddress) &sarea->front_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] drmAddMap(front_handle) failed. Disabling DRI\n"); - DRICloseScreen(pScreen); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n", - (int)sarea->front_handle); - } - - if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)(sarea->back_offset + pI830->LinearAddr), - sarea->back_size, DRM_AGP, 0, - (drmAddress) &sarea->back_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] drmAddMap(back_handle) failed. Disabling DRI\n"); - DRICloseScreen(pScreen); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n", - (int)sarea->back_handle); - - if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)sarea->depth_offset + pI830->LinearAddr, - sarea->depth_size, DRM_AGP, 0, - (drmAddress) &sarea->depth_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n"); - DRICloseScreen(pScreen); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08x\n", - (int)sarea->depth_handle); - - if (pI830->mmModeFlags & I830_KERNEL_TEX) { - if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)sarea->tex_offset + pI830->LinearAddr, - sarea->tex_size, DRM_AGP, 0, - (drmAddress) &sarea->tex_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n"); - DRICloseScreen(pScreen); - return FALSE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] textures = 0x%08x\n", - (int)sarea->tex_handle); - } - return TRUE; -} - - -void -I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (sarea->front_handle) { - drmRmMap(pI830->drmSubFD, sarea->front_handle); - sarea->front_handle = 0; - } - if (sarea->back_handle) { - drmRmMap(pI830->drmSubFD, sarea->back_handle); - sarea->back_handle = 0; - } - if (sarea->depth_handle) { - drmRmMap(pI830->drmSubFD, sarea->depth_handle); - sarea->depth_handle = 0; - } - if (sarea->tex_handle) { - drmRmMap(pI830->drmSubFD, sarea->tex_handle); - sarea->tex_handle = 0; - } -} - static void -I830InitTextureHeap(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +I830InitTextureHeap(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + if (pI830->textures == NULL) + return; + /* Start up the simple memory manager for agp space */ drmI830MemInitHeap drmHeap; drmHeap.region = I830_MEM_REGION_AGP; drmHeap.start = 0; - drmHeap.size = sarea->tex_size; - + drmHeap.size = pI830->textures->size; + if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP, &drmHeap, sizeof(drmHeap))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Failed to initialized agp heap manager\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] Initialized kernel agp heap manager, %d\n", - sarea->tex_size); + "[drm] Initialized kernel agp heap manager, %ld\n", + pI830->textures->size); I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, - sarea->log_tex_granularity); + pI830->TexGranularity); } } +/** + * Sets up mappings for static, lifetime-fixed allocations, and inital SAREA + * setup. + */ Bool I830DRIDoMappings(ScreenPtr pScreen) { @@ -817,8 +797,8 @@ I830DRIDoMappings(ScreenPtr pScreen) (int)pI830DRI->regs); if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)pI830->LpRing->mem.Start + pI830->LinearAddr, - pI830->LpRing->mem.Size, DRM_AGP, 0, + (drm_handle_t)pI830->LpRing->mem->offset + pI830->LinearAddr, + pI830->LpRing->mem->size, DRM_AGP, 0, (drmAddress) &pI830->ring_map) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(ring_map) failed. Disabling DRI\n"); @@ -833,9 +813,16 @@ I830DRIDoMappings(ScreenPtr pScreen) return FALSE; } + if (IS_G33CLASS(pI830)) { + if (!I830SetHWS(pScrn, pI830->hw_status->offset)) { + DRICloseScreen(pScreen); + return FALSE; + } + } /* init to zero to be safe */ sarea->front_handle = 0; sarea->back_handle = 0; + sarea->third_handle = 0; sarea->depth_handle = 0; sarea->tex_handle = 0; @@ -846,21 +833,31 @@ I830DRIDoMappings(ScreenPtr pScreen) pScrn->pScreen->width = pScrn->virtualX; pScrn->pScreen->height = pScrn->virtualY; - /* this will map the screen regions */ - if (!I830UpdateDRIBuffers(pScrn, sarea)) { - /* screen mappings probably failed */ - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] drmAddMap(screen mappings) failed. Disabling DRI\n"); - return FALSE; + /* If we are using the kernel memory manager, we have to delay SAREA and + * mapping setup until our buffers are pinned at EnterVT, losing the + * opportunity to fail cleanly early on. + */ + if (pI830->memory_manager == NULL) { + if (!i830_update_dri_buffers(pScrn)) { + /* screen mappings probably failed */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAddMap(screen mappings) failed. " + "Disabling DRI\n"); + DRICloseScreen(pScreen); + return FALSE; + } } - if (pI830->PciInfo->chipType != PCI_CHIP_845_G && - pI830->PciInfo->chipType != PCI_CHIP_I830_M) { + if (pI830->allocate_classic_textures) + I830InitTextureHeap(pScrn); + + if (DEVICE_ID(pI830->PciInfo) != PCI_CHIP_845_G && + DEVICE_ID(pI830->PciInfo) != PCI_CHIP_I830_M) { I830SetParam(pScrn, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 ); } pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; - pI830DRI->deviceID = pI830->PciInfo->chipType; + pI830DRI->deviceID = DEVICE_ID(pI830->PciInfo); pI830DRI->width = pScrn->virtualX; pI830DRI->height = pScrn->virtualY; pI830DRI->mem = pScrn->videoRam * 1024; @@ -896,12 +893,20 @@ I830DRIResume(ScreenPtr pScreen) { pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD, +#if XSERVER_LIBPCIACCESS + ((pI830->PciInfo->domain << 8) | + pI830->PciInfo->bus), + pI830->PciInfo->dev, + pI830->PciInfo->func +#else ((pciConfigPtr) pI830-> PciInfo->thisCard)->busnum, ((pciConfigPtr) pI830-> PciInfo->thisCard)->devnum, ((pciConfigPtr) pI830-> - PciInfo->thisCard)->funcnum); + PciInfo->thisCard)->funcnum +#endif + ); if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -927,6 +932,10 @@ I830DRICloseScreen(ScreenPtr pScreen) DPRINTF(PFX, "I830DRICloseScreen\n"); +#ifdef DAMAGE + REGION_UNINIT(pScreen, &pI830->driRegion); +#endif + if (pI830DRI->irq) { drmCtlUninstHandler(pI830->drmSubFD); pI830DRI->irq = 0; @@ -939,10 +948,10 @@ I830DRICloseScreen(ScreenPtr pScreen) if (pI830->pDRIInfo) { if (pI830->pDRIInfo->devPrivate) { xfree(pI830->pDRIInfo->devPrivate); - pI830->pDRIInfo->devPrivate = 0; + pI830->pDRIInfo->devPrivate = NULL; } DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; } if (pI830->pVisualConfigs) xfree(pI830->pVisualConfigs); @@ -972,17 +981,6 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) DPRINTF(PFX, "I830DRIFinishScreenInit\n"); - /* Have shadow run only while there is 3d active. - */ -#if 0 - if (pI830->allowPageFlip && pI830->drmMinor >= 1) { - shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0); - } - else -#endif - pI830->allowPageFlip = 0; - - if (!DRIFinishScreenInit(pScreen)) return FALSE; @@ -991,12 +989,20 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD, +#if XSERVER_LIBPCIACCESS + ((pI830->PciInfo->domain << 8) | + pI830->PciInfo->bus), + pI830->PciInfo->dev, + pI830->PciInfo->func +#else ((pciConfigPtr) pI830-> PciInfo->thisCard)->busnum, ((pciConfigPtr) pI830-> PciInfo->thisCard)->devnum, ((pciConfigPtr) pI830-> - PciInfo->thisCard)->funcnum); + PciInfo->thisCard)->funcnum +#endif + ); if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -1013,7 +1019,62 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) } } -void +#ifdef DAMAGE +/* This should be done *before* XAA syncs, + * Otherwise will have to sync again??? + */ +static void +I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, CARD32 dst) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); + + if (pScrn->bitsPerPixel == 32) { + cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + br13 |= 3 << 24; + } else { + cmd = (XY_SRC_COPY_BLT_CMD); + br13 |= 1 << 24; + } + + for (i = 0 ; i < num ; i++, pbox++) { + BEGIN_LP_RING(8); + OUT_RING(cmd); + OUT_RING(br13); + OUT_RING((pbox->y1 << 16) | pbox->x1); + OUT_RING((pbox->y2 << 16) | pbox->x2); + OUT_RING(dst); + OUT_RING((pbox->y1 << 16) | pbox->x1); + OUT_RING(br13 & 0xffff); + OUT_RING(pI830->front_buffer->offset); + ADVANCE_LP_RING(); + } +} + +static void +I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + I830Ptr pI830 = I830PTR(pScrn); + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + + /* Don't want to do this when no 3d is active and pages are + * right-way-round : + */ + if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0) + return; + + I830DRIDoRefreshArea(pScrn, num, pbox, pI830->back_buffer->offset); + + if (pI830->third_buffer) { + I830DRIDoRefreshArea(pScrn, num, pbox, pI830->third_buffer->offset); + } + + DamageEmpty(pI830->pDamage); +} +#endif + +static void I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext) @@ -1023,21 +1084,102 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, if (syncType == DRI_3D_SYNC && oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (in)\n"); + *pI830->last_3d = LAST_3D_OTHER; + if (!pScrn->vtSema) return; pI830->LockHeld = 1; - I830RefreshRing(pScrn); + i830_refresh_ring(pScrn); + + I830EmitFlush(pScrn); + +#ifdef DAMAGE + if (!pI830->pDamage && pI830->allowPageFlip) { + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); + pI830->pDamage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, + pScreen, pPix); + + if (pI830->pDamage == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No screen damage record, page flipping disabled\n"); + pI830->allowPageFlip = FALSE; + } else { + DamageRegister(&pPix->drawable, pI830->pDamage); + + DamageDamageRegion(&pPix->drawable, + &WindowTable[pScreen->myNum]->winSize); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Damage tracking initialized for page flipping\n"); + } + } +#endif } else if (syncType == DRI_2D_SYNC && oldContextType == DRI_NO_CONTEXT && newContextType == DRI_2D_CONTEXT) { - pI830->LockHeld = 0; +#ifdef DAMAGE + drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); +#endif + if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (out)\n"); + + if (!pScrn->vtSema) + return; + +#ifdef DAMAGE + if (pI830->pDamage) { + RegionPtr pDamageReg = DamageRegion(pI830->pDamage); + + if (pDamageReg) { + RegionRec region; + int nrects; + + REGION_NULL(pScreen, ®ion); + REGION_SUBTRACT(pScreen, ®ion, pDamageReg, &pI830->driRegion); + + if ((nrects = REGION_NUM_RECTS(®ion))) + I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(®ion)); + + REGION_UNINIT(pScreen, ®ion); + } + } +#endif + + I830EmitFlush(pScrn); + +#ifdef DAMAGE + /* Try flipping back to the front page if necessary */ + if (sPriv && !sPriv->pf_enabled && sPriv->pf_current_page != 0) { + drm_i915_flip_t flip = { .pipes = 0 }; + + if (sPriv->pf_current_page & (0x3 << 2)) { + sPriv->pf_current_page = sPriv->pf_current_page & 0x3; + sPriv->pf_current_page |= (sPriv->third_handle ? 2 : 1) << 2; + + flip.pipes |= 0x2; + } + + if (sPriv->pf_current_page & 0x3) { + sPriv->pf_current_page = sPriv->pf_current_page & (0x3 << 2); + sPriv->pf_current_page |= sPriv->third_handle ? 2 : 1; + + flip.pipes |= 0x1; + } + + drmCommandWrite(pI830->drmSubFD, DRM_I915_FLIP, &flip, sizeof(flip)); + + if (sPriv->pf_current_page != 0) + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[dri] %s: kernel failed to unflip buffers.\n", __func__); + } +#endif + + pI830->LockHeld = 0; } else if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (other)\n"); } @@ -1047,7 +1189,6 @@ I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) { ScreenPtr pScreen = pWin->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); BoxPtr pbox = REGION_RECTS(prgn); int nbox = REGION_NUM_RECTS(prgn); @@ -1059,6 +1200,13 @@ I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) I830SelectBuffer(pScrn, I830_SELECT_BACK); I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + + if (I830PTR(pScrn)->third_buffer) { + I830SelectBuffer(pScrn, I830_SELECT_THIRD); + I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + } + pbox++; } @@ -1085,7 +1233,7 @@ I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) } I830SelectBuffer(pScrn, I830_SELECT_FRONT); - pI830->AccelInfoRec->NeedToSync = TRUE; + i830MarkSync(pScrn); } /* This routine is a modified form of XAADoBitBlt with the calls to @@ -1115,9 +1263,9 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, BoxPtr pbox = REGION_RECTS(prgnSrc); int nbox = REGION_NUM_RECTS(prgnSrc); - BoxPtr pboxNew1 = 0; - BoxPtr pboxNew2 = 0; - DDXPointPtr pptNew1 = 0; + BoxPtr pboxNew1 = NULL; + BoxPtr pboxNew2 = NULL; + DDXPointPtr pptNew1 = NULL; DDXPointPtr pptSrc = &ptOldOrg; int dx = pParent->drawable.x - ptOldOrg.x; @@ -1232,7 +1380,11 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, I830SelectBuffer(pScrn, I830_SELECT_BACK); I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); - if (!IS_I96X(pI830)) { + if (pI830->third_buffer) { + I830SelectBuffer(pScrn, I830_SELECT_THIRD); + I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + } + if (!IS_I965G(pI830)) { I830SelectBuffer(pScrn, I830_SELECT_DEPTH); I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); } @@ -1248,8 +1400,7 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } - - pI830->AccelInfoRec->NeedToSync = TRUE; + i830MarkSync(pScrn); } /* Use callbacks from dri.c to support pageflipping mode for a single @@ -1259,10 +1410,6 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, * allocate and free 3d-specific memory on demand. */ - - - - /* Use the miext/shadow module to maintain a list of dirty rectangles. * These are blitted to the back buffer to keep both buffers clean * during page-flipping when the 3d application isn't fullscreen. @@ -1275,99 +1422,21 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, * might be faster, but seems like a lot more work... */ - -#if 0 -/* This should be done *before* XAA syncs, - * Otherwise will have to sync again??? - */ static void -I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) +I830DRISetPfMask(ScreenPtr pScreen, int pfMask) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - RegionPtr damage = &pBuf->damage; - int i, num = REGION_NUM_RECTS(damage); - BoxPtr pbox = REGION_RECTS(damage); drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); - int cmd, br13; - - /* Don't want to do this when no 3d is active and pages are - * right-way-round : - */ - if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0) - return; - br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); - - if (pScrn->bitsPerPixel == 32) { - cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - br13 |= 3 << 24; - } else { - cmd = (XY_SRC_COPY_BLT_CMD); - br13 |= 1 << 24; - } - - for (i = 0 ; i < num ; i++, pbox++) { - BEGIN_LP_RING(8); - OUT_RING(cmd); - OUT_RING(br13); - OUT_RING((pbox->y1 << 16) | pbox->x1); - OUT_RING((pbox->y2 << 16) | pbox->x2); - OUT_RING(pI830->BackBuffer.Start); - OUT_RING((pbox->y1 << 16) | pbox->x1); - OUT_RING(br13 & 0xffff); - OUT_RING(pI830->FrontBuffer.Start); - ADVANCE_LP_RING(); - } -} -#endif - -static void -I830EnablePageFlip(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); - - pSAREAPriv->pf_enabled = pI830->allowPageFlip; - pSAREAPriv->pf_active = 0; - - if (pI830->allowPageFlip) { - int br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); - - BEGIN_LP_RING(8); - if (pScrn->bitsPerPixel == 32) { - OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - br13 |= 3 << 24; - } else { - OUT_RING(XY_SRC_COPY_BLT_CMD); - br13 |= 1 << 24; - } - - OUT_RING(br13); - OUT_RING(0); - OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX); - OUT_RING(pI830->BackBuffer.Start); - OUT_RING(0); - OUT_RING(br13 & 0xffff); - OUT_RING(pI830->FrontBuffer.Start); - ADVANCE_LP_RING(); - - pSAREAPriv->pf_active = 1; - } + if (pI830->allowPageFlip && pfMask) { + pSAREAPriv->pf_enabled = pI830->allowPageFlip; + pSAREAPriv->pf_active = pfMask; + } else + pSAREAPriv->pf_active = 0; } -static void -I830DisablePageFlip(ScreenPtr pScreen) -{ - drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); - - pSAREAPriv->pf_active = 0; -} - - +#if !DRI_SUPPORTS_CLIP_NOTIFY static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen) { @@ -1375,16 +1444,20 @@ I830DRITransitionSingleToMulti3d(ScreenPtr pScreen) * -- Field in sarea, plus bumping the window counters. * -- DRM needs to cope with Front-to-Back swapbuffers. */ - I830DisablePageFlip(pScreen); + I830DRISetPfMask(pScreen, 0); } static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + /* Let the remaining 3d app start page flipping again. */ - I830EnablePageFlip(pScreen); + I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0); } +#endif /* !DRI_SUPPORTS_CLIP_NOTIFY */ static void I830DRITransitionTo3d(ScreenPtr pScreen) @@ -1392,10 +1465,11 @@ I830DRITransitionTo3d(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - I830EnablePageFlip(pScreen); - pI830->have3DWindows = 1; -} + I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0); + pI830->want_vblank_interrupts = TRUE; + I830DRISetVBlankInterrupt(pScrn, TRUE); +} static void I830DRITransitionTo2d(ScreenPtr pScreen) @@ -1404,128 +1478,290 @@ I830DRITransitionTo2d(ScreenPtr pScreen) I830Ptr pI830 = I830PTR(pScrn); drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); - /* Try flipping back to the front page if necessary */ - if (sPriv->pf_current_page == 1) - drmCommandNone(pI830->drmSubFD, DRM_I830_FLIP); - - /* Shut down shadowing if we've made it back to the front page: - */ - if (sPriv->pf_current_page == 0) { - I830DisablePageFlip(pScreen); - } + I830DRISetPfMask(pScreen, 0); - pI830->have3DWindows = 0; + sPriv->pf_enabled = 0; + pI830->want_vblank_interrupts = FALSE; + I830DRISetVBlankInterrupt(pScrn, FALSE); } - -/** - * Update the SAREA fields with the most recent values. - * This gets called after the screen orientation/rotation changes. - */ -Bool -I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +#if DRI_SUPPORTS_CLIP_NOTIFY +static void +I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - ScreenPtr pScreen = pScrn->pScreen; - Bool success; - - I830DRIUnmapScreenRegions(pScrn, sarea); + unsigned pfMask = 0; + + REGION_UNINIT(pScreen, &pI830->driRegion); + REGION_NULL(pScreen, &pI830->driRegion); + + if (num > 0) { + drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); + BoxRec crtcBox[2]; + unsigned numvisible[2] = { 0, 0 }; + int i, j; + + crtcBox[0].x1 = sPriv->planeA_x; + crtcBox[0].y1 = sPriv->planeA_y; + crtcBox[0].x2 = crtcBox[0].x1 + sPriv->planeA_w; + crtcBox[0].y2 = crtcBox[0].y1 + sPriv->planeA_h; + crtcBox[1].x1 = sPriv->planeB_x; + crtcBox[1].y1 = sPriv->planeB_y; + crtcBox[1].x2 = crtcBox[1].x1 + sPriv->planeB_w; + crtcBox[1].y2 = crtcBox[1].y1 + sPriv->planeB_h; + + for (i = 0; i < 2; i++) { + for (j = 0; j < num; j++) { + WindowPtr pWin = ppWin[j]; + + if (pWin) { + if (RECT_IN_REGION(pScreen, &pWin->clipList, &crtcBox[i]) != + rgnOUT) + numvisible[i]++; + + if (i == 0) + REGION_UNION(pScreen, &pI830->driRegion, &pWin->clipList, + &pI830->driRegion); + } + } - sarea->front_tiled = pI830->front_tiled; - sarea->back_tiled = pI830->back_tiled; - sarea->depth_tiled = pI830->depth_tiled; - sarea->rotated_tiled = pI830->rotated_tiled; -#if 0 - sarea->rotated2_tiled = pI830->rotated2_tiled; -#endif + if (numvisible[i] == 1) + pfMask |= 1 << i; + } + } else + REGION_NULL(pScreen, &pI830->driRegion); - if (pI830->rotation == RR_Rotate_0) { - sarea->front_offset = pI830->FrontBuffer.Start; - /* Don't use FrontBuffer.Size here as it includes the pixmap cache area - * Instead, calculate the entire framebuffer. - */ - sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp; - } else { - /* Need to deal with rotated2 once we have dual head DRI */ - sarea->front_offset = pI830->RotatedMem.Start; - sarea->front_size = pI830->RotatedMem.Size; - } + I830DRISetPfMask(pScreen, pfMask); +} +#endif /* DRI_SUPPORTS_CLIP_NOTIFY */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] init sarea width,height = %d x %d (pitch %d)\n", - pScreen->width, pScreen->height,pScrn->displayWidth); +/** + * Update the SAREA fields with current buffer information. + * + * Most of the SAREA fields are already updated by i830_do_addmap(). + * + * This does include other SAREA initialization which will actually be constant + * over the lifetime of the server. + */ +static void +i830_update_sarea(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +{ + ScreenPtr pScreen = pScrn->pScreen; + I830Ptr pI830 = I830PTR(pScrn); sarea->width = pScreen->width; sarea->height = pScreen->height; - sarea->back_offset = pI830->BackBuffer.Start; - sarea->back_size = pI830->BackBuffer.Size; - sarea->depth_offset = pI830->DepthBuffer.Start; - sarea->depth_size = pI830->DepthBuffer.Size; - sarea->tex_offset = pI830->TexMem.Start; - sarea->tex_size = pI830->TexMem.Size; - sarea->log_tex_granularity = pI830->TexGranularity; sarea->pitch = pScrn->displayWidth; sarea->virtualX = pScrn->virtualX; sarea->virtualY = pScrn->virtualY; - switch (pI830->rotation) { - case RR_Rotate_0: - sarea->rotation = 0; - break; - case RR_Rotate_90: - sarea->rotation = 90; - break; - case RR_Rotate_180: - sarea->rotation = 180; - break; - case RR_Rotate_270: - sarea->rotation = 270; - break; - default: - sarea->rotation = 0; + sarea->front_tiled = (pI830->front_buffer->tiling != TILE_NONE); + sarea->back_tiled = (pI830->back_buffer->tiling != TILE_NONE); + if (pI830->third_buffer != NULL) + sarea->third_tiled = (pI830->third_buffer->tiling != TILE_NONE); + else + sarea->third_tiled = FALSE; + sarea->depth_tiled = (pI830->depth_buffer->tiling != TILE_NONE); + sarea->rotated_tiled = FALSE; + + sarea->log_tex_granularity = pI830->TexGranularity; + + sarea->front_bo_handle = -1; + sarea->back_bo_handle = -1; + sarea->third_bo_handle = -1; + sarea->depth_bo_handle = -1; +#ifdef XF86DRI_MM + if (pI830->front_buffer->bo.size) + sarea->front_bo_handle = pI830->front_buffer->bo.handle; + if (pI830->back_buffer->bo.size) + sarea->back_bo_handle = pI830->back_buffer->bo.handle; + if (pI830->third_buffer != NULL && pI830->third_buffer->bo.size) + sarea->third_bo_handle = pI830->third_buffer->bo.handle; + if (pI830->depth_buffer->bo.size) + sarea->depth_bo_handle = pI830->depth_buffer->bo.handle; +#endif + + /* The rotation is now handled entirely by the X Server, so just leave the + * DRI unaware. + */ + sarea->rotation = 0; + sarea->rotated_offset = -1; + sarea->rotated_size = 0; + sarea->rotated_pitch = pScrn->displayWidth; +} + +/** + * Updates the DRI mapping for the given i830_memory struct, with the given + * flags. + */ +static int +i830_do_addmap(ScrnInfoPtr pScrn, i830_memory *mem, + drm_handle_t *sarea_handle, int *sarea_size, int *sarea_offset) +{ + I830Ptr pI830 = I830PTR(pScrn); + int size = mem->size; + + if (mem == pI830->front_buffer) { + /* Workaround for XAA pixmap cache: Don't use front_buffer->size + * and instead, calculate the visible frontbuffer size and round to + * avoid irritating the assertions of older DRI drivers. + */ + size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * + pI830->cpp); + } + + if (*sarea_handle != 0 && + (*sarea_size != size || *sarea_offset != mem->offset)) + { + drmRmMap(pI830->drmSubFD, *sarea_handle); + *sarea_handle = 0; + *sarea_size = 0; + *sarea_offset = 0; + } + + if (*sarea_handle == 0) { + int ret; + + ret = drmAddMap(pI830->drmSubFD, + (drm_handle_t)(mem->offset + pI830->LinearAddr), + size, DRM_AGP, 0, + (drmAddress) sarea_handle); + if (ret == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] mapped %s at 0x%08lx, handle = 0x%08x\n", + mem->name, mem->offset + pI830->LinearAddr, + (int)*sarea_handle); + *sarea_size = size; + *sarea_offset = mem->offset; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to map %s at 0x%08lx\n", + mem->name, mem->offset + pI830->LinearAddr); + return FALSE; + } + } + + return TRUE; +} + +/** + * Updates the DRM mappings with the current buffer information. + * + * Some old DRI drivers may be unprepared for buffers actually moving at + * runtime, which would likely result in bus errors on software fallbacks or + * hangs or misrendering on hardware rendering. + */ +static Bool +i830_update_dri_mappings(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (!i830_do_addmap(pScrn, pI830->front_buffer, &sarea->front_handle, + &sarea->front_size, &sarea->front_offset)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n"); + return FALSE; + } + + if (!i830_do_addmap(pScrn, pI830->back_buffer, &sarea->back_handle, + &sarea->back_size, &sarea->back_offset)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n"); + return FALSE; + } + + if (pI830->third_buffer) { + if (!i830_do_addmap(pScrn, pI830->third_buffer, &sarea->third_handle, + &sarea->third_size, &sarea->third_offset)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n"); + return FALSE; + } + } else { + sarea->third_handle = 0; + sarea->third_offset = 0; + sarea->third_size = 0; } - if (pI830->rotation == RR_Rotate_0) { - sarea->rotated_offset = -1; - sarea->rotated_size = 0; + + if (!i830_do_addmap(pScrn, pI830->depth_buffer, &sarea->depth_handle, + &sarea->depth_size, &sarea->depth_offset)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n"); + return FALSE; } - else { - sarea->rotated_offset = pI830->FrontBuffer.Start; - sarea->rotated_size = pI830->FrontBuffer.Size; + + if (pI830->allocate_classic_textures) { + if (!i830_do_addmap(pScrn, pI830->textures, &sarea->tex_handle, + &sarea->tex_size, &sarea->tex_offset)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n"); + return FALSE; + } } - /* This is the original pitch */ - sarea->rotated_pitch = pI830->displayWidth; + return TRUE; +} - success = I830DRIMapScreenRegions(pScrn, sarea); +static void +i830_update_screen_private(ScrnInfoPtr pScrn, drmI830Sarea *sarea) +{ + I830Ptr pI830 = I830PTR(pScrn); - if (success && (pI830->mmModeFlags & I830_KERNEL_TEX)) - I830InitTextureHeap(pScrn, sarea); + pI830->pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr; + pI830->pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp; + pI830->pDRIInfo->frameBufferSize = sarea->front_size; +#if DRI_DRIVER_FRAMEBUFFER_MAP + pI830->pDRIInfo->hFrameBuffer = sarea->front_handle; +#endif +} - return success; +/** + * Update the SAREA fields, DRI mappings, and screen info passed through the + * protocol. + * + * This gets called both at startup and after any of the buffers might have + * been relocated. + */ +Bool +i830_update_dri_buffers(ScrnInfoPtr pScrn) +{ + ScreenPtr pScreen = pScrn->pScreen; + drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); + Bool success; + + success = i830_update_dri_mappings(pScrn, sarea); + if (!success) + return FALSE; + i830_update_sarea(pScrn, sarea); + i830_update_screen_private(pScrn, sarea); + + return TRUE; } Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on) { I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); drmI830VBlankPipe pipe; + /* If we have no 3d running, then don't bother enabling the vblank + * interrupt. + */ + if (!pI830->want_vblank_interrupts) + on = FALSE; + if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) { if (on) { - if (pI830->planeEnabled[1]) { + if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled) if (pI830->drmMinor >= 6) pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B; else pipe.pipe = DRM_I830_VBLANK_PIPE_B; - } else + else pipe.pipe = DRM_I830_VBLANK_PIPE_A; } else { pipe.pipe = 0; } if (drmCommandWrite(pI830->drmSubFD, DRM_I830_SET_VBLANK_PIPE, &pipe, sizeof (pipe))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Vblank Pipe Setup Failed\n"); return FALSE; } } @@ -1541,7 +1777,7 @@ I830DRILock(ScrnInfoPtr pScrn) if (pI830->directRenderingEnabled && !pI830->LockHeld) { DRILock(screenInfo.screens[pScrn->scrnIndex], 0); pI830->LockHeld = 1; - I830RefreshRing(pScrn); + i830_refresh_ring(pScrn); return TRUE; } else |