diff options
-rw-r--r-- | man/intel.man | 5 | ||||
-rw-r--r-- | src/i830.h | 19 | ||||
-rw-r--r-- | src/i830_accel.c | 6 | ||||
-rw-r--r-- | src/i830_common.h | 9 | ||||
-rw-r--r-- | src/i830_dri.c | 196 | ||||
-rw-r--r-- | src/i830_dri.h | 2 | ||||
-rw-r--r-- | src/i830_driver.c | 287 | ||||
-rw-r--r-- | src/i830_exa.c | 9 | ||||
-rw-r--r-- | src/i830_memory.c | 434 |
9 files changed, 629 insertions, 338 deletions
diff --git a/man/intel.man b/man/intel.man index 2b197119..efe34d7e 100644 --- a/man/intel.man +++ b/man/intel.man @@ -128,9 +128,8 @@ Default: XVideo is enabled for configurations where it is supported. Enable support for the legacy i915_dri.so 3D driver. This will, among other things, make the 2D driver tell libGL to load the 3D driver i915_dri.so instead of the newer i915tex_dri.so. -This option is only used for chipsets in the range i830-i945. -Default for i830-i945 series: Enabled for i915 drm versions < 1.7.0. Otherwise -disabled. +This option is only used for chipsets in the range i830-i945. +Default for i830-i945 series: Enabled. Default for i810: The option is not used. Default for i965: The option is always true. .TP @@ -166,6 +166,10 @@ struct _i830_memory { i830_memory *prev; /** @} */ +#ifdef XF86DRI_MM + drmBO bo; + Bool lifetime_fixed_offset; +#endif }; typedef struct { @@ -291,7 +295,13 @@ typedef struct _I830Rec { /* These are set in PreInit and never changed. */ long FbMapSize; - i830_memory *memory_list; /**< Linked list of video memory allocations */ + /** + * Linked list of video memory allocations. The head and tail are + * dummy entries that bound the allocation area. + */ + i830_memory *memory_list; + /** Linked list of buffer object memory allocations */ + i830_memory *bo_list; long stolen_size; /**< bytes of pre-bound stolen memory */ int gtt_acquired; /**< whether we currently own the AGP */ @@ -334,8 +344,7 @@ typedef struct _I830Rec { int TexGranularity; int drmMinor; - int mmModeFlags; - int mmSize; + Bool allocate_classic_textures; Bool want_vblank_interrupts; #ifdef DAMAGE @@ -640,6 +649,7 @@ extern void I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size); +void i830_allocator_fini(ScrnInfoPtr pScrn); void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix); void i830_reset_allocations(ScrnInfoPtr pScrn); @@ -742,6 +752,9 @@ extern const int I830CopyROP[16]; /* Flags for memory allocation function */ #define NEED_PHYSICAL_ADDR 0x00000001 #define ALIGN_BOTH_ENDS 0x00000002 +#define NEED_NON_STOLEN 0x00000004 +#define NEED_LIFETIME_FIXED 0x00000008 +#define ALLOW_SHARING 0x00000010 /* Chipset registers for VIDEO BIOS memory RW access */ #define _855_DRAM_RW_CONTROL 0x58 diff --git a/src/i830_accel.c b/src/i830_accel.c index 5cbad44e..4d9ea790 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -254,6 +254,12 @@ I830RefreshRing(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + /* If we're reaching RefreshRing as a result of grabbing the DRI lock + * before we've set up the ringbuffer, don't bother. + */ + if (pI830->LpRing->mem == NULL) + return; + pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; pI830->LpRing->tail = INREG(LP_RING + RING_TAIL); pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); diff --git a/src/i830_common.h b/src/i830_common.h index 9c8616cd..1ca26422 100644 --- a/src/i830_common.h +++ b/src/i830_common.h @@ -138,6 +138,15 @@ typedef struct { int third_offset; int third_size; unsigned int third_tiled; + + /* buffer object handles for the static buffers. May change + * over the lifetime of the client, though it doesn't in our current + * implementation. + */ + unsigned int front_bo_handle; + unsigned int back_bo_handle; + unsigned int third_bo_handle; + unsigned int depth_bo_handle; } drmI830Sarea; /* Flags for perf_boxes diff --git a/src/i830_dri.c b/src/i830_dri.c index e2b42b49..c25a0843 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -124,11 +124,20 @@ static void I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, static void I830DRITransitionTo2d(ScreenPtr pScreen); static void I830DRITransitionTo3d(ScreenPtr pScreen); -static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen); -static void I830DRITransitionSingleToMulti3d(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 (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 @@ -491,7 +500,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" @@ -546,16 +556,6 @@ I830DRIScreenInit(ScreenPtr pScreen) 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->front_buffer->offset; - 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) @@ -591,41 +591,39 @@ I830DRIScreenInit(ScreenPtr pScreen) pDRIInfo->MoveBuffers = I830DRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; - { -#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1 - int major, minor, patch; - - DRIQueryVersion(&major, &minor, &patch); - -#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3 - if (minor >= 3) -#endif #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 && DRIINFO_MAJOR_VERSION == 5 - if (minor >= 1) -#endif #if DRI_SUPPORTS_CLIP_NOTIFY - pDRIInfo->ClipNotify = I830DRIClipNotify; + 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 -#endif /* DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1 */ - } pDRIInfo->TransitionTo2d = I830DRITransitionTo2d; pDRIInfo->TransitionTo3d = I830DRITransitionTo3d; -#if DRIINFO_MAJOR_VERSION > 5 || \ - (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1) - if (!pDRIInfo->ClipNotify) +#if !DRI_SUPPORTS_CLIP_NOTIFY + pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d; + pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d; #endif - { - pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d; - pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d; - } /* do driver-independent DRI screen initialization here */ if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) { @@ -638,26 +636,24 @@ I830DRIScreenInit(ScreenPtr pScreen) 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; + unsigned int 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 */ { @@ -725,27 +721,6 @@ I830DRIScreenInit(ScreenPtr pScreen) return FALSE; } pI830->drmMinor = version->version_minor; - if (version->version_minor < 7) { - if (pI830->mmModeFlags & I830_KERNEL_MM) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Unable to use TTM-based memory manager with DRM version %d.%d\n", - version->version_major, version->version_minor); - pI830->mmModeFlags &= ~I830_KERNEL_MM; - - i830_free_memory(pScrn, pI830->memory_manager); - pI830->memory_manager = NULL; - - if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) { - pI830->mmModeFlags |= I830_KERNEL_TEX; - - if (!i830_allocate_texture_memory(pScrn)) { - I830DRICloseScreen(pScreen); - drmFreeVersion(version); - return FALSE; - } - } - } - } #ifdef DAMAGE if (pI830->allowPageFlip && pI830->drmMinor < 9) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -763,7 +738,7 @@ I830DRIScreenInit(ScreenPtr pScreen) */ if ((pDRIInfo->clientDriverName == I830ClientDriverName) && - (pI830->mmModeFlags & I830_KERNEL_TEX)) { + (pI830->allocate_classic_textures)) { pDRIInfo->clientDriverName = I830LegacyClientDriverName; } @@ -775,32 +750,33 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) { ScreenPtr pScreen = pScrn->pScreen; I830Ptr pI830 = I830PTR(pScrn); + drm_handle_t front_handle; -#if 1 /* Remove this soon - see bug 5714 */ - pI830->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * - pScrn->virtualY * pI830->cpp); -#endif + pI830->pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr; + pI830->pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp; + pI830->pDRIInfo->frameBufferSize = + ROUND_TO_PAGE(pI830->pDRIInfo->frameBufferStride * pScrn->virtualY); - /* The I965G isn't ready for the front buffer mapping to be moved around, - * because of issues with rmmap, it seems. - */ - if (!IS_I965G(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); + 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, + &front_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(front_handle) failed. Disabling DRI\n"); + DRICloseScreen(pScreen); + return FALSE; } + sarea->front_handle = front_handle; +#if DRI_DRIVER_FRAMEBUFFER_MAP + pI830->pDRIInfo->hFrameBuffer = front_handle; +#endif + + 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), @@ -842,7 +818,7 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08x\n", (int)sarea->depth_handle); - if (pI830->mmModeFlags & I830_KERNEL_TEX) { + if (pI830->allocate_classic_textures) { if (drmAddMap(pI830->drmSubFD, (drm_handle_t)sarea->tex_offset + pI830->LinearAddr, sarea->tex_size, DRM_AGP, 0, @@ -1547,6 +1523,7 @@ I830DRISetPfMask(ScreenPtr pScreen, int pfMask) pSAREAPriv->pf_active = 0; } +#if !DRI_SUPPORTS_CLIP_NOTIFY static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen) { @@ -1567,6 +1544,7 @@ I830DRITransitionMultiToSingle3d(ScreenPtr pScreen) */ I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0); } +#endif /* !DRI_SUPPORTS_CLIP_NOTIFY */ static void I830DRITransitionTo3d(ScreenPtr pScreen) @@ -1690,6 +1668,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) sarea->third_offset = 0; sarea->third_size = 0; } + sarea->depth_offset = pI830->depth_buffer->offset; sarea->depth_size = pI830->depth_buffer->size; if (pI830->textures != NULL) { @@ -1704,6 +1683,21 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) sarea->virtualX = pScrn->virtualX; sarea->virtualY = pScrn->virtualY; + 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. */ @@ -1714,7 +1708,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) success = I830DRIMapScreenRegions(pScrn, sarea); - if (success && (pI830->mmModeFlags & I830_KERNEL_TEX)) + if (success && pI830->allocate_classic_textures) I830InitTextureHeap(pScrn, sarea); return success; diff --git a/src/i830_dri.h b/src/i830_dri.h index a2cf78ec..b6a83662 100644 --- a/src/i830_dri.h +++ b/src/i830_dri.h @@ -9,7 +9,7 @@ #define I830_MAX_DRAWABLES 256 #define I830_MAJOR_VERSION 1 -#define I830_MINOR_VERSION 8 +#define I830_MINOR_VERSION 9 #define I830_PATCHLEVEL 0 #define I830_REG_SIZE 0x80000 diff --git a/src/i830_driver.c b/src/i830_driver.c index 712b2ddb..1fbf9d56 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -290,7 +290,6 @@ typedef enum { OPTION_TILING, #ifdef XF86DRI_MM OPTION_INTELTEXPOOL, - OPTION_INTELMMSIZE, #endif OPTION_TRIPLEBUFFER, } I830Opts; @@ -313,7 +312,6 @@ static OptionInfoRec I830Options[] = { {OPTION_TILING, "Tiling", OPTV_BOOLEAN, {0}, TRUE}, #ifdef XF86DRI_MM {OPTION_INTELTEXPOOL,"Legacy3D", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_INTELMMSIZE, "AperTexSize", OPTV_INTEGER, {0}, FALSE}, #endif {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} @@ -714,6 +712,55 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, } } +#if 0 +/* This code ended up unused, but will be at least a reference when we let the + * front buffer move. + */ +static void +i830UpdateFrontOffset(ScrnInfoPtr pScrn) +{ + ScreenPtr pScreen = pScrn->pScreen; + I830Ptr pI830 = I830PTR(pScrn); + + /* If we are still in ScreenInit, there is no screen pixmap to be updated + * yet. We'll fix it up at CreateScreenResources. + */ + if (pI830->starting) + return; + + /* Update buffer locations, which may have changed as a result of + * i830_bind_all_memory(). + */ + pScrn->fbOffset = pI830->front_buffer->offset; + if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen), + -1, -1, -1, -1, -1, + (pointer)(pI830->FbBase + + pScrn->fbOffset))) + FatalError("Couldn't adjust screen pixmap\n"); +} + +/** + * Adjust the screen pixmap for the current location of the front buffer. + * This is done at EnterVT when buffers are bound as long as the resources + * have already been created, but the first EnterVT happens before + * CreateScreenResources. + */ +static Bool +i830CreateScreenResources(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + + pScreen->CreateScreenResources = pI830->CreateScreenResources; + if (!(*pScreen->CreateScreenResources)(pScreen)) + return FALSE; + + i830UpdateFrontOffset(pScrn); + + return TRUE; +} +#endif + int i830_output_clones (ScrnInfoPtr pScrn, int type_mask) { @@ -1322,50 +1369,22 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->directRenderingDisabled = TRUE; } - pI830->mmModeFlags = 0; - if (!pI830->directRenderingDisabled) { - pI830->mmModeFlags = I830_KERNEL_TEX; -#ifdef XF86DRI_MM - Bool tmp = FALSE; - - if (!IS_I965G(pI830)) - pI830->mmModeFlags |= I830_KERNEL_MM; -#endif + pI830->allocate_classic_textures = TRUE; from = X_PROBED; #ifdef XF86DRI_MM - if (xf86GetOptValBool(pI830->Options, - OPTION_INTELTEXPOOL, &tmp)) { - from = X_CONFIG; - if (tmp) { - pI830->mmModeFlags |= I830_KERNEL_TEX; - pI830->mmModeFlags &= ~I830_KERNEL_MM; - } else { - pI830->mmModeFlags &= ~I830_KERNEL_TEX; - pI830->mmModeFlags |= I830_KERNEL_MM; - } - } -#endif + if (!IS_I965G(pI830)) { + Bool tmp; - xf86DrvMsg(pScrn->scrnIndex, from, - "Will %stry to allocate texture pool " - "for old Mesa 3D driver.\n", - (pI830->mmModeFlags & I830_KERNEL_TEX) ? - "" : "not "); - -#ifdef XF86DRI_MM - pI830->mmSize = I830_MM_MAXSIZE; - from = X_INFO; - if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE, - &(pI830->mmSize))) { - from = X_CONFIG; + if (xf86GetOptValBool(pI830->Options, + OPTION_INTELTEXPOOL, &tmp)) { + from = X_CONFIG; + if (!tmp) + pI830->allocate_classic_textures = FALSE; + } } - xf86DrvMsg(pScrn->scrnIndex, from, - "Will try to reserve %d kiB of AGP aperture space\n" - "\tfor the DRM memory manager.\n", - pI830->mmSize); #endif } } @@ -2139,12 +2158,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) int i; Bool allocation_done = FALSE; MessageType from; -#ifdef XF86DRI - Bool driDisabled; -#ifdef XF86DRI_MM - unsigned long savedMMSize; -#endif -#endif pScrn = xf86Screens[pScreen->myNum]; pI830 = I830PTR(pScrn); @@ -2238,6 +2251,23 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScrn->videoRam &= ~3; } +#ifdef XF86DRI + /* Check for appropriate bpp and module support to initialize DRI. */ + if (!I830CheckDRIAvailable(pScrn)) { + pI830->directRenderingDisabled = TRUE; + } + + /* If DRI hasn't been explicitly disabled, try to initialize it. + * It will be used by the memory allocator. + */ + if (!pI830->directRenderingDisabled) + pI830->directRenderingEnabled = I830DRIScreenInit(pScreen); + else + pI830->directRenderingEnabled = FALSE; +#else + pI830->directRenderingEnabled = FALSE; +#endif + /* Set up our video memory allocator for the chosen videoRam */ if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -2323,12 +2353,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * for it, and if there's also enough to allow tiling to be enabled. */ - if (!I830CheckDRIAvailable(pScrn)) { - pI830->directRenderingDisabled = TRUE; -#ifdef XF86DRI_MM - pI830->mmSize = 0; -#endif - } #ifdef I830_XV /* @@ -2338,7 +2362,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->XvEnabled = !pI830->XvDisabled; #endif - if (!pI830->directRenderingDisabled) { + if (pI830->directRenderingEnabled) { int savedDisplayWidth = pScrn->displayWidth; Bool tiled = FALSE; @@ -2368,25 +2392,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } - /* Attempt several rounds of allocation to get 2d and 3d memory to fit: + /* Attempt two rounds of allocation to get 2d and 3d memory to fit: * - * 0: tiled, large memory manager - * 1: tiled, small memory manager - * 2: untiled, large - * 3: untiled, small + * 0: untiled + * 1: tiled */ -#ifdef XF86DRI_MM - savedMMSize = pI830->mmSize; -#define MM_TURNS 4 -#else #define MM_TURNS 2 -#endif for (i = 0; i < MM_TURNS; i++) { - if (!tiled && i < 2) + if (!tiled && i == 0) continue; - if (i >= MM_TURNS/2) { + if (i >= 1) { /* For further allocations, disable tiling */ pI830->tiling = FALSE; pScrn->displayWidth = savedDisplayWidth; @@ -2397,26 +2414,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->allowPageFlip = FALSE; } -#ifdef XF86DRI_MM - if (i & 1) { - /* For this allocation, switch to a smaller DRI memory manager - * size. - */ - pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE / KB(1); - } else { - pI830->mmSize = savedMMSize; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Attempting memory allocation with %s buffers and \n" - "\t %s DRI memory manager reservation:\n", - (i & 2) ? "untiled" : "tiled", - (i & 1) ? "small" : "large"); -#else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Attempting memory allocation with %s buffers:\n", + "Attempting memory allocation with %s buffers.\n", (i & 1) ? "untiled" : "tiled"); -#endif if (i830_allocate_2d_memory(pScrn) && i830_allocate_3d_memory(pScrn)) @@ -2438,10 +2438,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (i == MM_TURNS) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Not enough video memory. Disabling DRI.\n"); -#ifdef XF86DRI_MM - pI830->mmSize = 0; -#endif - pI830->directRenderingDisabled = TRUE; + pI830->directRenderingEnabled = FALSE; } } #endif @@ -2457,13 +2454,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) I830UnmapMMIO(pScrn); - i830_describe_allocations(pScrn, 1, ""); - if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support DRI with frame buffer width > 2048.\n"); pI830->tiling = FALSE; - pI830->directRenderingDisabled = TRUE; + pI830->directRenderingEnabled = FALSE; } pScrn->displayWidth = pScrn->displayWidth; @@ -2565,11 +2560,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef XF86DRI /* - * pI830->directRenderingDisabled is set once in PreInit. Reinitialise - * pI830->directRenderingEnabled based on it each generation. - */ - pI830->directRenderingEnabled = !pI830->directRenderingDisabled; - /* * Setup DRI after visuals have been established, but before fbScreenInit * is called. fbScreenInit will eventually call into the drivers * InitGLXVisuals call back. @@ -2580,26 +2570,21 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it " "needs HW cursor, 2D accel and AGPGART.\n"); pI830->directRenderingEnabled = FALSE; - i830_free_3d_memory(pScrn); } } - driDisabled = !pI830->directRenderingEnabled; - if (pI830->directRenderingEnabled) - pI830->directRenderingEnabled = I830DRIScreenInit(pScreen); + pI830->directRenderingEnabled = I830DRIDoMappings(pScreen); - if (!pI830->directRenderingEnabled) { + /* If we failed for any reason, free DRI memory. */ + if (!pI830->directRenderingEnabled) i830_free_3d_memory(pScrn); - } #else pI830->directRenderingEnabled = FALSE; #endif #ifdef XF86DRI - if (pI830->directRenderingEnabled) - pI830->directRenderingEnabled = I830DRIDoMappings(pScreen); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n", pI830->allowPageFlip ? "en" : "dis"); @@ -2696,6 +2681,14 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } else xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n"); +#ifdef XF86DRI + /* Must be called before EnterVT, so we can acquire the DRI lock when + * binding our memory. + */ + if (pI830->directRenderingEnabled) + pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen); +#endif + if (!I830EnterVT(scrnIndex, 0)) return FALSE; @@ -2718,12 +2711,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) I830InitVideo(pScreen); #endif -#ifdef XF86DRI - if (pI830->directRenderingEnabled) { - pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen); - } -#endif - /* Setup 3D engine, needed for rotation too */ IntelEmitInvarientState(pScrn); @@ -2732,7 +2719,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->directRenderingOpen = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n"); } else { - if (driDisabled) + if (pI830->directRenderingDisabled) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n"); else xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n"); @@ -2744,6 +2731,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScreen->SaveScreen = xf86SaveScreen; pI830->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = I830CloseScreen; +#if 0 + pI830->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = i830CreateScreenResources; +#endif if (!xf86CrtcScreenInit (pScreen)) return FALSE; @@ -2773,37 +2764,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->closing = FALSE; pI830->suspended = FALSE; -#ifdef XF86DRI_MM - if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) - { - if (pI830->memory_manager == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Too little AGP aperture space for DRM memory manager.\n" - "\tPlease increase AGP aperture size from BIOS configuration screen.\n" - "\tDisabling DRI.\n"); - pI830->directRenderingOpen = FALSE; - I830DRICloseScreen(pScreen); - pI830->directRenderingEnabled = FALSE; - } else { - unsigned long aperEnd = ROUND_DOWN_TO(pI830->memory_manager->offset + - pI830->memory_manager->size, - GTT_PAGE_SIZE) / GTT_PAGE_SIZE; - unsigned long aperStart = ROUND_TO(pI830->memory_manager->offset, - GTT_PAGE_SIZE) / GTT_PAGE_SIZE; - - if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart, - DRM_BO_MEM_TT)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Could not initialize the DRM memory manager.\n"); - - pI830->directRenderingOpen = FALSE; - I830DRICloseScreen(pScreen); - pI830->directRenderingEnabled = FALSE; - } - } - } -#endif /* XF86DRI_MM */ - return TRUE; } @@ -2864,7 +2824,7 @@ I830LeaveVT(int scrnIndex, int flags) if (pI830->directRenderingOpen) { DRILock(screenInfo.screens[pScrn->scrnIndex], 0); #ifdef XF86DRI_MM - if (pI830->mmModeFlags & I830_KERNEL_MM) { + if (pI830->memory_manager != NULL) { drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT); } #endif /* XF86DRI_MM */ @@ -2919,6 +2879,12 @@ I830EnterVT(int scrnIndex, int flags) if (!i830_bind_all_memory(pScrn)) return FALSE; + i830_describe_allocations(pScrn, 1, ""); + +#if 0 + i830UpdateFrontOffset(pScrn); +#endif + if (i830_check_error_state(pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Existing errors found in hardware state.\n"); @@ -2969,7 +2935,7 @@ I830EnterVT(int scrnIndex, int flags) sarea->texList[i].age = sarea->texAge; #ifdef XF86DRI_MM - if (pI830->mmModeFlags & I830_KERNEL_MM) { + if (pI830->memory_manager != NULL) { drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT); } #endif /* XF86DRI_MM */ @@ -3016,26 +2982,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) #endif pI830->closing = TRUE; -#ifdef XF86DRI - if (pI830->directRenderingOpen) { -#ifdef DAMAGE - if (pI830->pDamage) { - PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); - - DamageUnregister(&pPix->drawable, pI830->pDamage); - DamageDestroy(pI830->pDamage); - pI830->pDamage = NULL; - } -#endif -#ifdef XF86DRI_MM - if (pI830->mmModeFlags & I830_KERNEL_MM) { - drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); - } -#endif /* XF86DRI_MM */ - pI830->directRenderingOpen = FALSE; - I830DRICloseScreen(pScreen); - } -#endif if (pScrn->vtSema == TRUE) { I830LeaveVT(scrnIndex, 0); @@ -3070,7 +3016,22 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) #endif xf86_cursors_fini (pScreen); - i830_reset_allocations(pScrn); + i830_allocator_fini(pScrn); +#ifdef XF86DRI + if (pI830->directRenderingOpen) { +#ifdef DAMAGE + if (pI830->pDamage) { + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); + + DamageUnregister(&pPix->drawable, pI830->pDamage); + DamageDestroy(pI830->pDamage); + pI830->pDamage = NULL; + } +#endif + pI830->directRenderingOpen = FALSE; + I830DRICloseScreen(pScreen); + } +#endif if (I830IsPrimary(pScrn)) { xf86GARTCloseScreen(scrnIndex); diff --git a/src/i830_exa.c b/src/i830_exa.c index fdf94d7a..353ab8f2 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -458,9 +458,14 @@ I830EXAInit(ScreenPtr pScreen) pI830->EXADriverPtr->exa_major = 2; pI830->EXADriverPtr->exa_minor = 1; pI830->EXADriverPtr->memoryBase = pI830->FbBase; - pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset; - pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset + + if (pI830->exa_offscreen) { + pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset; + pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset + pI830->exa_offscreen->size; + } else { + pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize; + pI830->EXADriverPtr->memorySize = pI830->FbMapSize; + } pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS; DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, " diff --git a/src/i830_memory.c b/src/i830_memory.c index 15d3a489..23288588 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -108,6 +108,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) +/* Our hardware status area is just a single page */ +#define HWSTATUS_PAGE_SIZE GTT_PAGE_SIZE + +static i830_memory * +i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name, + long size, unsigned long alignment, int flags); + static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset, unsigned int pitch, unsigned int size, enum tile_format tile_format); @@ -146,10 +153,31 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem) { I830Ptr pI830 = I830PTR(pScrn); - if (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired) + if (mem == NULL || mem->bound) return TRUE; - if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) { +#ifdef XF86DRI_MM + if (mem->bo.size != 0) { + I830Ptr pI830 = I830PTR(pScrn); + int ret; + + ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 1); + if (ret == 0) { + mem->bound = TRUE; + mem->offset = mem->bo.offset; + mem->end = mem->bo.offset + mem->size; + return TRUE; + } else { + return FALSE; + } + } +#endif + + if (!pI830->gtt_acquired) + return TRUE; + + if (mem->key == -1 || + xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) { mem->bound = TRUE; return TRUE; } else { @@ -162,10 +190,28 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem) static Bool i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem) { - if (mem == NULL || mem->key == -1 || !mem->bound) + if (mem == NULL || !mem->bound) return TRUE; - if (xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) { +#ifdef XF86DRI_MM + if (mem->bo.size != 0) { + I830Ptr pI830 = I830PTR(pScrn); + int ret; + + ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 0); + if (ret == 0) { + mem->bound = FALSE; + /* Give buffer obviously wrong offset/end until it's re-pinned. */ + mem->offset = -1; + mem->end = -1; + return TRUE; + } else { + return FALSE; + } + } +#endif + + if (mem->key == -1 || xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) { mem->bound = FALSE; return TRUE; } else { @@ -179,15 +225,31 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem) if (mem == NULL) return; - /* Disconnect from the list of allocations */ + /* Free any AGP memory. */ + i830_unbind_memory(pScrn, mem); + +#ifdef XF86DRI_MM + if (mem->bo.size != 0) { + I830Ptr pI830 = I830PTR(pScrn); + + drmBOUnReference(pI830->drmSubFD, &mem->bo); + if (pI830->bo_list == mem) + pI830->bo_list = mem->next; + if (mem->next) + mem->next->prev = NULL; + if (mem->prev) + mem->prev->next = NULL; + xfree(mem->name); + xfree(mem); + return; + } +#endif + /* Disconnect from the list of allocations */ if (mem->prev != NULL) mem->prev->next = mem->next; if (mem->next != NULL) mem->next->prev = mem->prev; - /* Free any AGP memory. */ - i830_unbind_memory(pScrn, mem); - if (mem->key != -1) { xf86DeallocateGARTMemory(pScrn->scrnIndex, mem->key); mem->key = -1; @@ -231,7 +293,6 @@ i830_reset_allocations(ScrnInfoPtr pScrn) pI830->third_buffer = NULL; pI830->depth_buffer = NULL; pI830->textures = NULL; - pI830->memory_manager = NULL; #endif pI830->LpRing->mem = NULL; @@ -254,21 +315,27 @@ i830_free_3d_memory(ScrnInfoPtr pScrn) pI830->depth_buffer = NULL; i830_free_memory(pScrn, pI830->textures); pI830->textures = NULL; - i830_free_memory(pScrn, pI830->memory_manager); - pI830->memory_manager = NULL; #endif } /** * Initialize's the driver's video memory allocator to allocate in the * given range. + * + * This sets up the kernel memory manager to manage as much of the memory + * as we think it can, while leaving enough to us to fulfill our non-TTM + * static allocations. Some of these exist because of the need for physical + * addresses to reference. */ Bool -i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, - unsigned long size) +i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size) { I830Ptr pI830 = I830PTR(pScrn); i830_memory *start, *end; + int ret; +#ifdef XF86DRI_MM + int dri_major, dri_minor, dri_patch; +#endif start = xcalloc(1, sizeof(*start)); if (start == NULL) @@ -305,9 +372,89 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, pI830->memory_list = start; +#ifdef XF86DRI_MM + DRIQueryVersion(&dri_major, &dri_minor, &dri_patch); + + /* Now that we have our manager set up, initialize the kernel MM if + * possible, covering almost all of the aperture. We need libdri interface + * 5.4 or newer so we can rely on the lock being held after DRIScreenInit, + * rather than after DRIFinishScreenInit. + */ + if (pI830->directRenderingEnabled && pI830->drmMinor >= 7 && + (dri_major > 5 || (dri_major == 5 && dri_minor >= 4))) + { + int mmsize; + + /* Take over all of the graphics aperture minus enough to for + * physical-address allocations of cursor/overlay registers. + */ + mmsize = size; + /* Overlay is always set up as fixed, currently. */ + if (!OVERLAY_NOPHYSICAL(pI830) && !IS_I965G(pI830)) { + mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE); + if (pI830->CursorNeedsPhysical) { + mmsize -= 2 * (ROUND_TO(HWCURSOR_SIZE, GTT_PAGE_SIZE) + + ROUND_TO(HWCURSOR_SIZE_ARGB, GTT_PAGE_SIZE)); + } + } + if (pI830->fb_compression) + mmsize -= MB(6); + /* Can't do TTM on stolen memory */ + mmsize -= pI830->stolen_size; + + /* Create the aperture allocation */ + pI830->memory_manager = + i830_allocate_aperture(pScrn, "DRI memory manager", + mmsize, GTT_PAGE_SIZE, + ALIGN_BOTH_ENDS | NEED_NON_STOLEN); + + if (pI830->memory_manager != NULL) { + /* Tell the kernel to manage it */ + ret = drmMMInit(pI830->drmSubFD, + pI830->memory_manager->offset / GTT_PAGE_SIZE, + pI830->memory_manager->size / GTT_PAGE_SIZE, + DRM_BO_MEM_TT); + if (ret != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize kernel memory manager\n"); + i830_free_memory(pScrn, pI830->memory_manager); + pI830->memory_manager = NULL; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate space for kernel memory manager\n"); + i830_free_memory(pScrn, pI830->memory_manager); + pI830->memory_manager = NULL; + } + } +#endif /* XF86DRI_MM */ + return TRUE; } +void +i830_allocator_fini(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + /* Free most of the allocations */ + i830_reset_allocations(pScrn); + +#ifdef XF86DRI_MM + /* The memory manager is more special */ + if (pI830->memory_manager) { + drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); + i830_free_memory(pScrn, pI830->memory_manager); + pI830->memory_manager = NULL; + } +#endif /* XF86DRI_MM */ + + /* Free the start/end markers */ + free(pI830->memory_list->next); + free(pI830->memory_list); + pI830->memory_list = NULL; +} + /** * Reads a GTT entry for the memory at the given offset and returns the * physical address. @@ -441,6 +588,9 @@ i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name, mem->offset = ROUND_TO(pI830->stolen_size, alignment); } } + if ((flags & NEED_NON_STOLEN) && mem->offset < pI830->stolen_size) { + mem->offset = ROUND_TO(pI830->stolen_size, alignment); + } mem->end = mem->offset + size; if (flags & ALIGN_BOTH_ENDS) @@ -509,25 +659,105 @@ i830_allocate_agp_memory(ScrnInfoPtr pScrn, i830_memory *mem, int flags) return TRUE; } +#ifdef XF86DRI_MM +static i830_memory * +i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name, + unsigned long size, unsigned long align, int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + i830_memory *mem; + unsigned long mask; + int ret; + + assert((flags & NEED_PHYSICAL_ADDR) == 0); + + /* Only allocate page-sized increments. */ + size = ALIGN(size, GTT_PAGE_SIZE); + align = ROUND_TO(align, GTT_PAGE_SIZE); + + mem = xcalloc(1, sizeof(*mem)); + if (mem == NULL) + return NULL; + + mem->name = xstrdup(name); + if (name == NULL) { + xfree(mem); + return NULL; + } + + mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE | + DRM_BO_FLAG_MEM_TT; + if (flags & ALLOW_SHARING) + mask |= DRM_BO_FLAG_SHAREABLE; + + ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL, + drm_bo_type_dc, mask, 0, &mem->bo); + if (ret) { + xfree(mem->name); + xfree(mem); + return NULL; + } + /* Give buffer obviously wrong offset/end until it's pinned. */ + mem->offset = -1; + mem->end = -1; + mem->size = size; + if (flags & NEED_LIFETIME_FIXED) { + if (!i830_bind_memory(pScrn, mem)) { + drmBOUnReference(pI830->drmSubFD, &mem->bo); + xfree(mem->name); + xfree(mem); + return NULL; + } + mem->lifetime_fixed_offset = TRUE; + } + + /* Insert new allocation into the list */ + mem->prev = NULL; + mem->next = pI830->bo_list; + if (pI830->bo_list != NULL) + pI830->bo_list->prev = mem; + pI830->bo_list = mem; + + return mem; +} +#endif /* XF86DRI_MM */ /* Allocates video memory at the given size and alignment. * * The memory will be bound automatically when the driver is in control of the - * VT. + * VT. When the kernel memory manager is available and compatible with flags + * (that is, flags doesn't say that the allocation must include a physical + * address), that will be used for the allocation. + * + * flags: + * - NEED_PHYSICAL_ADDR: Allocates the memory physically contiguous, and return + * the bus address for that memory. + * - ALIGN_BOTH_ENDS: after choosing the alignment, align the end offset to + * @alignment as well. + * - NEED_NON-STOLEN: don't allow any part of the memory allocation to lie + * within stolen memory + * - NEED_LIFETIME_FIXED: don't allow the buffer object to move throughout + * the entire Screen lifetime. This means not using buffer objects, which + * get their offsets chosen at each EnterVT time. */ static i830_memory * i830_allocate_memory(ScrnInfoPtr pScrn, const char *name, unsigned long size, unsigned long alignment, int flags) { + I830Ptr pI830 = I830PTR(pScrn); i830_memory *mem; - mem = i830_allocate_aperture(pScrn, name, size, alignment, flags); - if (mem == NULL) - return NULL; + if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR)) { + return i830_allocate_memory_bo(pScrn, name, size, alignment, flags); + } else { + mem = i830_allocate_aperture(pScrn, name, size, alignment, flags); + if (mem == NULL) + return NULL; - if (!i830_allocate_agp_memory(pScrn, mem, flags)) { - i830_free_memory(pScrn, mem); - return NULL; + if (!i830_allocate_agp_memory(pScrn, mem, flags)) { + i830_free_memory(pScrn, mem); + return NULL; + } } mem->tiling = TILE_NONE; @@ -559,6 +789,12 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name, if (tile_format == TILE_NONE) return i830_allocate_memory(pScrn, name, size, alignment, flags); + /* XXX: for now, refuse to tile with movable buffer object allocations, + * until we can move the set_fence (and failure recovery) into bind time. + */ + if (pI830->memory_manager != NULL && !(flags & NEED_LIFETIME_FIXED)) + return NULL; + /* Only allocate page-sized increments. */ size = ALIGN(size, GTT_PAGE_SIZE); @@ -584,7 +820,7 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name, aper_align = alignment; fence_divide = 1; - mem = i830_allocate_aperture(pScrn, name, aper_size, aper_align, flags); + mem = i830_allocate_memory(pScrn, name, aper_size, aper_align, flags); if (mem == NULL && !IS_I965G(pI830)) { /* For the older hardware with stricter fencing limits, if we * couldn't allocate with the large alignment, try relaxing the @@ -600,8 +836,8 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name, break; } - mem = i830_allocate_aperture(pScrn, name, aper_size, - aper_align / fence_divide, flags); + mem = i830_allocate_memory(pScrn, name, aper_size, + aper_align / fence_divide, flags); } } @@ -619,12 +855,6 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name, return NULL; } - /* Allocate any necessary AGP memory to back this allocation */ - if (!i830_allocate_agp_memory(pScrn, mem, flags)) { - i830_free_memory(pScrn, mem); - return NULL; - } - /* Set up the fence registers. */ for (i = 0; i < fence_divide; i++) { i830_set_fence(pScrn, pI830->next_fence++, @@ -657,7 +887,7 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix) } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sMemory allocation layout:\n", prefix); + "%sFixed memory allocation layout:\n", prefix); for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) { char phys_suffix[32] = ""; @@ -687,6 +917,31 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%s0x%08lx: end of aperture\n", prefix, pI830->FbMapSize); + +#ifdef XF86DRI_MM + if (pI830->memory_manager) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sBO memory allocation layout:\n", prefix); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%s0x%08lx: start of memory manager\n", + prefix, pI830->memory_manager->offset); + for (mem = pI830->bo_list; mem != NULL; mem = mem->next) { + if (mem->bound) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix, + mem->offset, mem->end - 1, mem->name, + mem->size / 1024); + } else { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sunpinned : %s (%ld kB)\n", prefix, + mem->name, mem->size / 1024); + } + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%s0x%08lx: end of memory manager\n", + prefix, pI830->memory_manager->end); + } +#endif /* XF86DRI_MM */ } static Bool @@ -697,9 +952,13 @@ i830_allocate_ringbuffer(ScrnInfoPtr pScrn) if (pI830->noAccel || pI830->LpRing->mem != NULL) return TRUE; + /* We don't have any mechanism in the DRM yet to alert it that we've moved + * the ringbuffer since init time, so allocate it fixed for its lifetime. + */ pI830->LpRing->mem = i830_allocate_memory(pScrn, "ring buffer", PRIMARY_RINGBUFFER_SIZE, - GTT_PAGE_SIZE, 0); + GTT_PAGE_SIZE, + NEED_LIFETIME_FIXED); if (pI830->LpRing->mem == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate Ring Buffer space\n"); @@ -719,7 +978,7 @@ static Bool i830_allocate_overlay(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int flags = NEED_PHYSICAL_ADDR; + int flags = NEED_PHYSICAL_ADDR | NEED_LIFETIME_FIXED; /* Only allocate if overlay is going to be enabled. */ if (!pI830->XvEnabled) @@ -729,6 +988,10 @@ i830_allocate_overlay(ScrnInfoPtr pScrn) flags = 0; if (!IS_I965G(pI830)) { + /* XXX: The lifetime fixed offset for overlay register is bogus, and we + * should just tell i830_video.c about the new location at EnterVT + * time. + */ pI830->overlay_regs = i830_allocate_memory(pScrn, "overlay registers", OVERLAY_SIZE, GTT_PAGE_SIZE, flags); @@ -796,7 +1059,7 @@ IsTileable(ScrnInfoPtr pScrn, int pitch) */ static i830_memory * i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, - Bool secondary, int flags) + Bool secondary) { unsigned int pitch = pScrn->displayWidth * pI830->cpp; unsigned long minspace, avail; @@ -804,9 +1067,16 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, int align; long size, fb_height; char *name; + int flags; i830_memory *front_buffer = NULL; Bool tiling; + /* The front buffer is currently marked as NEED_LIFETIME_FIXED because + * DRIDoMappings is the only caller of the rm/add map functions, + * and it's only called at startup. This should be easily fixable. + */ + flags = NEED_LIFETIME_FIXED | ALLOW_SHARING; + /* Clear everything first. */ memset(FbMemBox, 0, sizeof(*FbMemBox)); @@ -891,8 +1161,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, else align = KB(512); front_buffer = i830_allocate_memory_tiled(pScrn, name, size, - pitch, align, - 0, TILE_XMAJOR); + pitch, align, flags, + TILE_XMAJOR); } /* If not, attempt it linear */ @@ -923,7 +1193,7 @@ i830_allocate_cursor_buffers(ScrnInfoPtr pScrn) /* Try to allocate one big blob for our cursor memory. This works * around a limitation in the FreeBSD AGP driver that allows only one - * physical allocation larger than a page, and could allos us + * physical allocation larger than a page, and could allow us * to pack the cursors smaller. */ size = xf86_config->num_crtc * (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB); @@ -1127,12 +1397,12 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn) pI830->front_buffer_2 = i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302, - &pI830->FbMemBox2, TRUE, 0); + &pI830->FbMemBox2, TRUE); if (pI830->front_buffer_2 == NULL) return FALSE; } pI830->front_buffer = - i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE, 0); + i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE); if (pI830->front_buffer == NULL) return FALSE; @@ -1150,8 +1420,13 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn) size += 1920 * 1088 * 2 * 2; size = ROUND_TO_PAGE(size); - pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen", - size, 1, 0); + /* EXA has no way to tell it that the offscreen memory manager has + * moved its base and all the contents with it, so we have to have + * it locked in place for the whole driver instance. + */ + pI830->exa_offscreen = + i830_allocate_memory(pScrn, "exa offscreen", + size, 1, NEED_LIFETIME_FIXED); if (pI830->exa_offscreen == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to allocate EXA offscreen memory."); @@ -1162,14 +1437,18 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn) #endif /* I830_USE_EXA */ if (!pI830->noAccel && !pI830->useEXA) { + /* The lifetime fixed offset of xaa scratch is probably not required, + * but we do some setup using it at XAAInit() time. And XAA may not + * end up being supported with TTM anyway. + */ pI830->xaa_scratch = i830_allocate_memory(pScrn, "xaa scratch", MAX_SCRATCH_BUFFER_SIZE, - GTT_PAGE_SIZE, 0); + GTT_PAGE_SIZE, NEED_LIFETIME_FIXED); if (pI830->xaa_scratch == NULL) { pI830->xaa_scratch = i830_allocate_memory(pScrn, "xaa scratch", MIN_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE, - 0); + NEED_LIFETIME_FIXED); if (pI830->xaa_scratch == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to allocate scratch buffer space\n"); @@ -1184,12 +1463,12 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn) pI830->xaa_scratch_2 = i830_allocate_memory(pScrn, "xaa scratch 2", MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE, - 0); + NEED_LIFETIME_FIXED); if (pI830->xaa_scratch_2 == NULL) { pI830->xaa_scratch_2 = i830_allocate_memory(pScrn, "xaa scratch 2", MIN_SCRATCH_BUFFER_SIZE, - GTT_PAGE_SIZE, 0); + GTT_PAGE_SIZE, NEED_LIFETIME_FIXED); if (pI830->xaa_scratch_2 == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to allocate secondary scratch " @@ -1235,15 +1514,22 @@ i830_allocate_backbuffer(ScrnInfoPtr pScrn, i830_memory **buffer, { size = ROUND_TO_PAGE(pitch * ALIGN(height, 16)); *buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch, - GTT_PAGE_SIZE, ALIGN_BOTH_ENDS, + GTT_PAGE_SIZE, + ALIGN_BOTH_ENDS | + NEED_LIFETIME_FIXED | + ALLOW_SHARING, TILE_XMAJOR); } - /* Otherwise, just allocate it linear */ + /* Otherwise, just allocate it linear. The offset must stay constant + * currently because we don't ever update the DRI maps after screen init. + */ if (*buffer == NULL) { size = ROUND_TO_PAGE(pitch * height); *buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE, - ALIGN_BOTH_ENDS); + ALIGN_BOTH_ENDS | + NEED_LIFETIME_FIXED | + ALLOW_SHARING); } if (*buffer == NULL) { @@ -1283,16 +1569,21 @@ i830_allocate_depthbuffer(ScrnInfoPtr pScrn) pI830->depth_buffer = i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch, - GTT_PAGE_SIZE, ALIGN_BOTH_ENDS, + GTT_PAGE_SIZE, + ALIGN_BOTH_ENDS | + NEED_LIFETIME_FIXED | + ALLOW_SHARING, tile_format); } - /* Otherwise, allocate it linear. */ + /* Otherwise, allocate it linear. The offset must stay constant + * currently because we don't ever update the DRI maps after screen init. + */ if (pI830->depth_buffer == NULL) { size = ROUND_TO_PAGE(pitch * height); pI830->depth_buffer = i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE, - 0); + ALLOW_SHARING | NEED_LIFETIME_FIXED); } if (pI830->depth_buffer == NULL) { @@ -1311,17 +1602,7 @@ i830_allocate_texture_memory(ScrnInfoPtr pScrn) unsigned long size; int i; - if (pI830->mmModeFlags & I830_KERNEL_MM) { - pI830->memory_manager = - i830_allocate_aperture(pScrn, "DRI memory manager", - pI830->mmSize * KB(1), GTT_PAGE_SIZE, - ALIGN_BOTH_ENDS); - /* XXX: try memory manager size backoff here? */ - if (pI830->memory_manager == NULL) - return FALSE; - } - - if (pI830->mmModeFlags & I830_KERNEL_TEX) { + if (pI830->allocate_classic_textures) { /* XXX: auto-sizing */ size = MB(32); i = myLog2(size / I830_NR_TEX_REGIONS); @@ -1338,8 +1619,13 @@ i830_allocate_texture_memory(ScrnInfoPtr pScrn) size / 1024); return FALSE; } - pI830->textures = i830_allocate_memory(pScrn, "textures", size, - GTT_PAGE_SIZE, 0); + /* The offset must stay constant currently because we don't ever update + * the DRI maps after screen init. + */ + pI830->textures = i830_allocate_memory(pScrn, "classic textures", size, + GTT_PAGE_SIZE, + ALLOW_SHARING | + NEED_LIFETIME_FIXED); if (pI830->textures == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to allocate texture space.\n"); @@ -1353,11 +1639,14 @@ i830_allocate_texture_memory(ScrnInfoPtr pScrn) static Bool i830_allocate_hwstatus(ScrnInfoPtr pScrn) { -#define HWSTATUS_PAGE_SIZE (4*1024) I830Ptr pI830 = I830PTR(pScrn); + /* The current DRM will leak the HWS mapping if we update the address + * after init (at best), so allocate it fixed for its lifetime + * (i.e. not through buffer objects). + */ pI830->hw_status = i830_allocate_memory(pScrn, "G33 hw status", - HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, 0); + HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, NEED_LIFETIME_FIXED); if (pI830->hw_status == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to allocate hw status page for G33.\n"); @@ -1630,6 +1919,12 @@ i830_bind_all_memory(ScrnInfoPtr pScrn) FatalError("Couldn't bind memory for %s\n", mem->name); } } +#ifdef XF86DRI_MM + for (mem = pI830->bo_list; mem != NULL; mem = mem->next) { + if (!mem->lifetime_fixed_offset && !i830_bind_memory(pScrn, mem)) + FatalError("Couldn't bind memory for BO %s\n", mem->name); + } +#endif } return TRUE; @@ -1652,6 +1947,15 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn) { i830_unbind_memory(pScrn, mem); } +#ifdef XF86DRI_MM + for (mem = pI830->bo_list; mem != NULL; mem = mem->next) { + /* Don't unpin objects which require that their offsets never + * change. + */ + if (!mem->lifetime_fixed_offset) + i830_unbind_memory(pScrn, mem); + } +#endif pI830->gtt_acquired = FALSE; |