From e80b9c24f4211dd99729eebbd4ed69f89a42cf40 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Apr 2006 07:13:17 +0000 Subject: [PATCH] add tiling/fence support for the miniglx driver --- src/mesa/drivers/dri/i915/server/intel.h | 44 ++- src/mesa/drivers/dri/i915/server/intel_dri.c | 268 +++++++++++++++++-- 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 606db974b1c..d7858a20c8d 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 # 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 8ea1cb6ff6c..169fdbece30 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. -- 2.30.2