summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDave Airlie <airliedfreedesktop.org>2006-04-05 07:13:17 +0000
committerDave Airlie <airliedfreedesktop.org>2006-04-05 07:13:17 +0000
commite80b9c24f4211dd99729eebbd4ed69f89a42cf40 (patch)
tree943b7a37da649772d787cb937ff24cd8d93973d7 /src
parent2e7af79f48a7bfa37c682ba8ab3426b4701fe58c (diff)
add tiling/fence support for the miniglx driver
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i915/server/intel.h44
-rw-r--r--src/mesa/drivers/dri/i915/server/intel_dri.c268
2 files changed, 292 insertions, 20 deletions
diff --git a/src/mesa/drivers/dri/i915/server/intel.h b/src/mesa/drivers/dri/i915/server/intel.h
index 606db974b1..d7858a20c8 100644
--- a/src/mesa/drivers/dri/i915/server/intel.h
+++ b/src/mesa/drivers/dri/i915/server/intel.h
@@ -137,11 +137,6 @@ typedef struct {
int space;
} I830RingBuffer;
-typedef struct {
- unsigned int Fence[8];
-} I830RegRec, *I830RegPtr;
-
-
typedef struct _I830Rec {
unsigned char *MMIOBase;
unsigned char *FbBase;
@@ -194,6 +189,7 @@ typedef struct _I830Rec {
int GttBound;
drm_handle_t ring_map;
+ unsigned int Fence[8];
} I830Rec;
@@ -271,6 +267,44 @@ typedef struct _I830Rec {
#define RING_INVALID 0x00000000
+/* Fence/Tiling ranges [0..7]
+ */
+#define FENCE 0x2000
+#define FENCE_NR 8
+
+#define I915G_FENCE_START_MASK 0x0ff00000
+
+#define I830_FENCE_START_MASK 0x07f80000
+
+#define FENCE_START_MASK 0x03F80000
+#define FENCE_X_MAJOR 0x00000000
+#define FENCE_Y_MAJOR 0x00001000
+#define FENCE_SIZE_MASK 0x00000700
+#define FENCE_SIZE_512K 0x00000000
+#define FENCE_SIZE_1M 0x00000100
+#define FENCE_SIZE_2M 0x00000200
+#define FENCE_SIZE_4M 0x00000300
+#define FENCE_SIZE_8M 0x00000400
+#define FENCE_SIZE_16M 0x00000500
+#define FENCE_SIZE_32M 0x00000600
+#define FENCE_SIZE_64M 0x00000700
+#define I915G_FENCE_SIZE_1M 0x00000000
+#define I915G_FENCE_SIZE_2M 0x00000100
+#define I915G_FENCE_SIZE_4M 0x00000200
+#define I915G_FENCE_SIZE_8M 0x00000300
+#define I915G_FENCE_SIZE_16M 0x00000400
+#define I915G_FENCE_SIZE_32M 0x00000500
+#define I915G_FENCE_SIZE_64M 0x00000600
+#define I915G_FENCE_SIZE_128M 0x00000700
+#define FENCE_PITCH_1 0x00000000
+#define FENCE_PITCH_2 0x00000010
+#define FENCE_PITCH_4 0x00000020
+#define FENCE_PITCH_8 0x00000030
+#define FENCE_PITCH_16 0x00000040
+#define FENCE_PITCH_32 0x00000050
+#define FENCE_PITCH_64 0x00000060
+#define FENCE_VALID 0x00000001
+
#include <mmio.h>
# define MMIO_IN8(base, offset) \
diff --git a/src/mesa/drivers/dri/i915/server/intel_dri.c b/src/mesa/drivers/dri/i915/server/intel_dri.c
index 8ea1cb6ff6..169fdbece3 100644
--- a/src/mesa/drivers/dri/i915/server/intel_dri.c
+++ b/src/mesa/drivers/dri/i915/server/intel_dri.c
@@ -46,6 +46,7 @@
#include "pciaccess.h"
static size_t drm_page_size;
+static int nextTile = 0;
#define xf86DrvMsg(...) do {} while(0)
static const int pitches[] = {
@@ -58,6 +59,237 @@ static const int pitches[] = {
static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);
+static unsigned long
+GetBestTileAlignment(unsigned long size)
+{
+ unsigned long i;
+
+ for (i = KB(512); i < size; i <<= 1)
+ ;
+
+ if (i > MB(64))
+ i = MB(64);
+
+ return i;
+}
+
+static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ int i;
+ unsigned char *MMIO = ctx->MMIOAddress;
+
+ for (i = 0; i < 8; i++) {
+ OUTREG(FENCE + i * 4, pI830->Fence[i]);
+ // if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+ fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]);
+ }
+}
+
+/* Tiled memory is good... really, really good...
+ *
+ * Need to make it less likely that we miss out on this - probably
+ * need to move the frontbuffer away from the 'guarenteed' alignment
+ * of the first memory segment, or perhaps allocate a discontigous
+ * framebuffer to get more alignment 'sweet spots'.
+ */
+static void
+SetFence(const DRIDriverContext *ctx, I830Rec *pI830,
+ int nr, unsigned int start, unsigned int pitch,
+ unsigned int size)
+{
+ unsigned int val;
+ unsigned int fence_mask = 0;
+ unsigned int fence_pitch;
+
+ if (nr < 0 || nr > 7) {
+ fprintf(stderr,
+ "SetFence: fence %d out of range\n",nr);
+ return;
+ }
+
+ pI830->Fence[nr] = 0;
+
+ if (IS_I9XX(pI830))
+ fence_mask = ~I915G_FENCE_START_MASK;
+ else
+ fence_mask = ~I830_FENCE_START_MASK;
+
+ if (start & fence_mask) {
+ fprintf(stderr,
+ "SetFence: %d: start (0x%08x) is not %s aligned\n",
+ nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
+ return;
+ }
+
+ if (start % size) {
+ fprintf(stderr,
+ "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
+ nr, start, size / 1024);
+ return;
+ }
+
+ if (pitch & 127) {
+ fprintf(stderr,
+ "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
+ nr, pitch);
+ return;
+ }
+
+ val = (start | FENCE_X_MAJOR | FENCE_VALID);
+
+ if (IS_I9XX(pI830)) {
+ switch (size) {
+ case MB(1):
+ val |= I915G_FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= I915G_FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= I915G_FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= I915G_FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= I915G_FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= I915G_FENCE_SIZE_32M;
+ break;
+ case MB(64):
+ val |= I915G_FENCE_SIZE_64M;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ return;
+ }
+ } else {
+ switch (size) {
+ case KB(512):
+ val |= FENCE_SIZE_512K;
+ break;
+ case MB(1):
+ val |= FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= FENCE_SIZE_32M;
+ break;
+ case MB(64):
+ val |= FENCE_SIZE_64M;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ return;
+ }
+ }
+
+ if (IS_I9XX(pI830))
+ fence_pitch = pitch / 512;
+ else
+ fence_pitch = pitch / 128;
+
+ switch (fence_pitch) {
+ case 1:
+ val |= FENCE_PITCH_1;
+ break;
+ case 2:
+ val |= FENCE_PITCH_2;
+ break;
+ case 4:
+ val |= FENCE_PITCH_4;
+ break;
+ case 8:
+ val |= FENCE_PITCH_8;
+ break;
+ case 16:
+ val |= FENCE_PITCH_16;
+ break;
+ case 32:
+ val |= FENCE_PITCH_32;
+ break;
+ case 64:
+ val |= FENCE_PITCH_64;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
+ return;
+ }
+
+ pI830->Fence[nr] = val;
+}
+
+static Bool
+MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem)
+{
+ int pitch, ntiles, i;
+
+ pitch = pMem->Pitch * ctx->cpp;
+ /*
+ * Simply try to break the region up into at most four pieces of size
+ * equal to the alignment.
+ */
+ ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
+ if (ntiles >= 4) {
+ return FALSE;
+ }
+
+ for (i = 0; i < ntiles; i++, nextTile++) {
+ SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment,
+ pitch, pMem->Alignment);
+ }
+ return TRUE;
+}
+
+static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ int i;
+
+ /* Clear out */
+ for (i = 0; i < 8; i++)
+ pI830->Fence[i] = 0;
+
+ nextTile = 0;
+
+ if (pI830->BackBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) {
+ fprintf(stderr,
+ "Activating tiled memory for the back buffer.\n");
+ } else {
+ fprintf(stderr,
+ "MakeTiles failed for the back buffer.\n");
+ pI830->allowPageFlip = FALSE;
+ }
+ }
+
+ if (pI830->DepthBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) {
+ fprintf(stderr,
+ "Activating tiled memory for the depth buffer.\n");
+ } else {
+ fprintf(stderr,
+ "MakeTiles failed for the depth buffer.\n");
+ }
+ }
+
+ return;
+}
+
static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830)
{
struct pci_device host_bridge;
@@ -303,6 +535,8 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
size = lineSize * lines;
size = ROUND_TO_PAGE(size);
+ align = GetBestTileAlignment(size);
+
ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
if (ret < size)
{
@@ -386,7 +620,7 @@ I830CleanupDma(const DRIDriverContext *ctx)
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
&info, sizeof(drmI830Init))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Cleanup Failed\n");
+ fprintf(stderr, "I830 Dma Cleanup Failed\n");
return FALSE;
}
@@ -418,11 +652,11 @@ I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
info.pitch = ctx->shared.virtualWidth;
info.back_pitch = pI830->BackBuffer.Pitch;
info.depth_pitch = pI830->DepthBuffer.Pitch;
- info.cpp = pI830->cpp;
+ info.cpp = ctx->cpp;
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
&info, sizeof(drmI830Init))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"I830 Dma Initialization Failed\n");
return FALSE;
}
@@ -481,7 +715,7 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
pI830->LpRing->mem.Start) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"I830SetRingRegs: Ring buffer start (%lx) violates its "
"mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
}
@@ -491,7 +725,7 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
pI830->LpRing->mem.Size - 4096) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
"mask (%x)\n", pI830->LpRing->mem.Size - 4096,
I830_RING_NR_PAGES);
@@ -506,6 +740,8 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
if (pI830->LpRing->space < 0)
pI830->LpRing->space += pI830->LpRing->mem.Size;
+
+ SetFenceRegs(ctx, pI830);
/* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
hacky hacky */
@@ -523,7 +759,7 @@ I830SetParam(const DRIDriverContext *ctx, int param, int value)
sp.value = value;
if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 SetParam Failed\n");
+ fprintf(stderr, "I830 SetParam Failed\n");
return FALSE;
}
@@ -555,7 +791,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar
(drm_handle_t)(sarea->back_offset),
sarea->back_size, DRM_AGP, 0,
&sarea->back_handle) < 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
return FALSE;
}
@@ -566,7 +802,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar
(drm_handle_t)sarea->depth_offset,
sarea->depth_size, DRM_AGP, 0,
&sarea->depth_handle) < 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
return FALSE;
}
@@ -577,7 +813,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar
(drm_handle_t)sarea->tex_offset,
sarea->tex_size, DRM_AGP, 0,
&sarea->tex_handle) < 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
return FALSE;
}
@@ -622,10 +858,10 @@ I830InitTextureHeap(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *s
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT_HEAP,
&drmHeap, sizeof(drmHeap))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] Failed to initialized agp heap manager\n");
} else {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ fprintf(stderr,
"[drm] Initialized kernel agp heap manager, %d\n",
sarea->tex_size);
@@ -670,18 +906,18 @@ I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
ctx->pciFunc);
if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] failure adding irq handler\n");
pI830->irq = 0;
return FALSE;
}
else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ fprintf(stderr,
"[drm] dma control initialized, using IRQ %d\n",
- pI830DRI->irq);
+ pI830->irq);
}
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n");
+ fprintf(stderr, "[dri] visual configs initialized\n");
return TRUE;
}
@@ -887,6 +1123,8 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
if (err == FALSE)
return FALSE;
+ I830SetupMemoryTiling(ctx, pI830);
+
/* Quick hack to clear the front & back buffers. Could also use
* the clear ioctl to do this, but would need to setup hw state
* first.