summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/intel.man5
-rw-r--r--src/i830.h19
-rw-r--r--src/i830_accel.c6
-rw-r--r--src/i830_common.h9
-rw-r--r--src/i830_dri.c196
-rw-r--r--src/i830_dri.h2
-rw-r--r--src/i830_driver.c287
-rw-r--r--src/i830_exa.c9
-rw-r--r--src/i830_memory.c434
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
diff --git a/src/i830.h b/src/i830.h
index ca48b522..a39514bd 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -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;