diff --git a/src/i830.h b/src/i830.h index 6e1f88a2..14de7f0e 100644 --- a/src/i830.h +++ b/src/i830.h @@ -286,7 +286,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 */ diff --git a/src/i830_driver.c b/src/i830_driver.c index 20c6c682..929a5410 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2403,8 +2403,6 @@ 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"); @@ -2632,6 +2630,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; @@ -2654,11 +2660,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); @@ -2802,6 +2803,7 @@ static Bool I830EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + ScreenPtr pScreen = pScrn->pScreen; I830Ptr pI830 = I830PTR(pScrn); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); int o; @@ -2823,6 +2825,18 @@ I830EnterVT(int scrnIndex, int flags) if (!i830_bind_all_memory(pScrn)) return FALSE; + i830_describe_allocations(pScrn, 1, ""); + + /* 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"); + if (i830_check_error_state(pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Existing errors found in hardware state.\n"); diff --git a/src/i830_exa.c b/src/i830_exa.c index fed4067b..e801d50d 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -405,9 +405,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, memorySize 0x%x\n", diff --git a/src/i830_memory.c b/src/i830_memory.c index d4e9bff0..80e3536e 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -155,10 +155,25 @@ 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 || !pI830->gtt_acquired) return TRUE; - if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) { +#ifdef XF86DRI_MM + if (mem->bo.size != 0) { + int ret; + + ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 1); + mem->offset = mem->bo.offset; + mem->end = mem->offset + mem->size; + if (ret) + return FALSE; + else + return TRUE; + } +#endif + + if (mem->key == -1 || + xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) { mem->bound = TRUE; return TRUE; } else { @@ -171,10 +186,23 @@ 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) + return FALSE; + else + return TRUE; + } +#endif + + if (mem->key == -1 || xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) { mem->bound = FALSE; return TRUE; } else { @@ -195,6 +223,12 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem) #ifdef XF86DRI_MM if (mem->bo.size != 0) { 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; @@ -615,7 +649,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name, { I830Ptr pI830 = I830PTR(pScrn); i830_memory *mem; - unsigned long hint, mask; + unsigned long mask; int ret; assert((flags & NEED_PHYSICAL_ADDR) == 0); @@ -635,14 +669,10 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name, } mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE | - DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE; - hint = DRM_BO_HINT_DONT_FENCE | DRM_BO_HINT_DONT_BLOCK | - DRM_BO_HINT_ALLOW_UNFENCED_MAP; + DRM_BO_FLAG_MEM_TT; - I830DRILock(pScrn); ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL, - drm_bo_type_dc, mask, hint, &mem->bo); - I830DRIUnlock(pScrn); + drm_bo_type_dc, mask, 0, &mem->bo); if (ret) { xfree(mem->name); xfree(mem); @@ -653,6 +683,13 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name, mem->end = mem->bo.start + size; mem->size = size; + /* 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 */ @@ -711,6 +748,12 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name, if (tile_format == TILING_NONE) return i830_allocate_memory(pScrn, name, size, alignment, flags); + /* XXX: for now, refuse to tile with buffer object allocations, + * until we can move the set_fence (and failure recovery) into EnterVT. + */ + if (pI830->memory_manager != NULL) + return NULL; + /* Only allocate page-sized increments. */ size = ALIGN(size, GTT_PAGE_SIZE); @@ -811,7 +854,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) { @@ -831,7 +874,7 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix) } else { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%s0x%08lx-0x%08lx: %s " - "(%ld kB, 0x%16llx physical)\n", + "(%ld kB, 0x%016llx physical)\n", prefix, mem->offset, mem->end - 1, mem->name, mem->size / 1024, mem->bus_addr); @@ -841,6 +884,25 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix) "%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) { + 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); + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%s0x%08lx: end of memory manager\n", + prefix, pI830->memory_manager->end); + } +#endif /* XF86DRI_MM */ + if (pI830->front_buffer != NULL) { i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer, pI830->front_tiled); @@ -1305,7 +1367,12 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn) #ifdef I830_USE_EXA if (pI830->useEXA) { - if (pI830->exa_offscreen == NULL) { + /* With the kernel memory manager, the exa offscreen allocation would + * change locations at EnterVT, which EXA is unprepared for. The + * performance of EXA offscreen memory management was low enough + * that just not using it is reasonable. + */ + if (pI830->exa_offscreen == NULL && pI830->memory_manager == NULL) { /* Default EXA to having 3 screens worth of offscreen memory space * (for pixmaps), plus a double-buffered, 1920x1088 video's worth. * @@ -1799,6 +1866,10 @@ i830_bind_all_memory(ScrnInfoPtr pScrn) FatalError("Couldn't bind memory for %s\n", mem->name); } } + for (mem = pI830->bo_list; mem != NULL; mem = mem->next) { + if (!i830_bind_memory(pScrn, mem)) + FatalError("Couldn't bind memory for BO %s\n", mem->name); + } } return TRUE; @@ -1821,6 +1892,8 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn) { i830_unbind_memory(pScrn, mem); } + for (mem = pI830->bo_list; mem != NULL; mem = mem->next) + i830_unbind_memory(pScrn, mem); pI830->gtt_acquired = FALSE;