summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2007-10-04 17:02:15 -0700
committerEric Anholt <eric@anholt.net>2007-10-11 12:17:14 -0700
commit4ca3550fb7d488741f8dc1ba3c8722393277c3b8 (patch)
tree5c87e871275ef3b6e42be58bf44a59bda558607c
parentf393a12d21eed668cf4771f022beded9a4c547c7 (diff)
Rework DRI buffer mappings and sarea setup to allow for moving buffers.
While this has been a desired feature for some time, to allow for reallocation of the front buffer, it was made more necessary by the desire to avoid requiring a NO_MOVE buffer type in TTM because buffer objects may not be left pinned over VT switch. This is a step towards making those buffers movable and resizable.
-rw-r--r--src/i830.h4
-rw-r--r--src/i830_common.h2
-rw-r--r--src/i830_dri.c346
-rw-r--r--src/i830_driver.c21
4 files changed, 191 insertions, 182 deletions
diff --git a/src/i830.h b/src/i830.h
index df95fb59..a34be61a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -635,12 +635,10 @@ extern Bool I830DRIDoMappings(ScreenPtr pScreen);
extern Bool I830DRIResume(ScreenPtr pScreen);
extern void I830DRICloseScreen(ScreenPtr pScreen);
extern Bool I830DRIFinishScreenInit(ScreenPtr pScreen);
-extern Bool I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
-extern void I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
-extern Bool I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
extern void I830DRIUnlock(ScrnInfoPtr pScrn);
extern Bool I830DRILock(ScrnInfoPtr pScrn);
extern Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on);
+Bool i830_update_dri_buffers(ScrnInfoPtr pScrn);
#endif
unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
diff --git a/src/i830_common.h b/src/i830_common.h
index a4c3b5a9..f3a7ea01 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -74,7 +74,7 @@ typedef struct {
unsigned int depth_offset;
unsigned int w;
unsigned int h;
- unsigned int pitch;
+ unsigned int pitch; /* Pitch of front buffer in units of pixels */
unsigned int pitch_bits;
unsigned int back_pitch;
unsigned int depth_pitch;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 4cddf3ba..0466410c 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -640,7 +640,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
/* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */
if (pDRIInfo->frameBufferSize != 0) {
int tmp;
- unsigned int fb_handle;
+ drm_handle_t fb_handle;
void *ptmp;
/* With the compat method, it will continue to report
@@ -743,149 +743,38 @@ I830DRIScreenInit(ScreenPtr pScreen)
return TRUE;
}
-Bool
-I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
-{
- ScreenPtr pScreen = pScrn->pScreen;
- I830Ptr pI830 = I830PTR(pScrn);
- drm_handle_t front_handle;
-
- pI830->pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
- pI830->pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
- pI830->pDRIInfo->frameBufferSize =
- ROUND_TO_PAGE(pI830->pDRIInfo->frameBufferStride * pScrn->virtualY);
-
- 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),
- 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 (pI830->third_buffer) {
- if (drmAddMap(pI830->drmSubFD,
- (drm_handle_t)(sarea->third_offset + pI830->LinearAddr),
- sarea->third_size, DRM_AGP, 0,
- (drmAddress) &sarea->third_handle) < 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "[drm] drmAddMap(third_handle) failed. Triple buffering "
- "inactive\n");
- i830_free_memory(pScrn, pI830->third_buffer);
- pI830->third_buffer = NULL;
- sarea->third_handle = 0;
- } else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
- (int)sarea->third_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->allocate_classic_textures) {
- 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->third_handle) {
- drmRmMap(pI830->drmSubFD, sarea->third_handle);
- sarea->third_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)
{
@@ -944,14 +833,17 @@ I830DRIDoMappings(ScreenPtr pScreen)
pScrn->pScreen->width = pScrn->virtualX;
pScrn->pScreen->height = pScrn->virtualY;
- /* this will map the screen regions */
- if (!I830UpdateDRIBuffers(pScrn, sarea)) {
+ 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->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 );
@@ -1639,17 +1531,24 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
#endif /* DRI_SUPPORTS_CLIP_NOTIFY */
/**
- * Update the SAREA fields with the most recent values.
- * This gets called after the screen orientation/rotation changes.
+ * 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.
*/
-Bool
-I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+static void
+i830_update_sarea(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
{
- I830Ptr pI830 = I830PTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
- Bool success;
+ I830Ptr pI830 = I830PTR(pScrn);
- I830DRIUnmapScreenRegions(pScrn, sarea);
+ sarea->width = pScreen->width;
+ sarea->height = pScreen->height;
+ sarea->pitch = pScrn->displayWidth;
+ sarea->virtualX = pScrn->virtualX;
+ sarea->virtualY = pScrn->virtualY;
sarea->front_tiled = (pI830->front_buffer->tiling != TILE_NONE);
sarea->back_tiled = (pI830->back_buffer->tiling != TILE_NONE);
@@ -1660,42 +1559,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
sarea->depth_tiled = (pI830->depth_buffer->tiling != TILE_NONE);
sarea->rotated_tiled = FALSE;
- sarea->front_offset = pI830->front_buffer->offset;
- /* Don't use front_buffer->size here as it includes the pixmap cache area
- * Instead, calculate the entire framebuffer.
- */
- sarea->front_size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY *
- pI830->cpp);
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "[drm] init sarea width,height = %d x %d (pitch %d)\n",
- pScreen->width, pScreen->height,pScrn->displayWidth);
-
- sarea->width = pScreen->width;
- sarea->height = pScreen->height;
- sarea->back_offset = pI830->back_buffer->offset;
- sarea->back_size = pI830->back_buffer->size;
- if (pI830->third_buffer != NULL) {
- sarea->third_offset = pI830->third_buffer->offset;
- sarea->third_size = pI830->third_buffer->size;
- } else {
- 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) {
- sarea->tex_offset = pI830->textures->offset;
- sarea->tex_size = pI830->textures->size;
- } else {
- sarea->tex_offset = 0;
- sarea->tex_size = 0;
- }
sarea->log_tex_granularity = pI830->TexGranularity;
- sarea->pitch = pScrn->displayWidth;
- sarea->virtualX = pScrn->virtualX;
- sarea->virtualY = pScrn->virtualY;
sarea->front_bo_handle = -1;
sarea->back_bo_handle = -1;
@@ -1719,13 +1583,149 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
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 (!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;
+ }
+
+ 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;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+i830_update_screen_private(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
- success = I830DRIMapScreenRegions(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
+}
- if (success && pI830->allocate_classic_textures)
- I830InitTextureHeap(pScrn, sarea);
+/**
+ * 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 success;
+ return TRUE;
}
Bool
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b3edb61a..d24c408a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3018,6 +3018,17 @@ I830EnterVT(int scrnIndex, int flags)
pI830->leaving = FALSE;
+#ifdef XF86DRI_MM
+ if (pI830->directRenderingEnabled) {
+ /* Unlock the memory manager first of all so that we can pin our
+ * buffer objects
+ */
+ if (pI830->memory_manager != NULL) {
+ drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
+ }
+ }
+#endif /* XF86DRI_MM */
+
if (I830IsPrimary(pScrn))
if (!i830_bind_all_memory(pScrn))
return FALSE;
@@ -3077,11 +3088,11 @@ I830EnterVT(int scrnIndex, int flags)
for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++)
sarea->texList[i].age = sarea->texAge;
-#ifdef XF86DRI_MM
- if (pI830->memory_manager != NULL) {
- drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
- }
-#endif /* XF86DRI_MM */
+ /* Update buffer offsets in sarea and mappings, since buffer offsets
+ * may have changed.
+ */
+ if (!i830_update_dri_buffers(pScrn))
+ FatalError("i830_update_dri_buffers() failed\n");
DPRINTF(PFX, "calling dri unlock\n");
DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);