diff options
author | Eric Anholt <eric@anholt.net> | 2007-02-22 10:41:09 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2007-02-23 12:50:49 -0800 |
commit | d3ac440e127c8a7716062852cd3b5e7943e289e4 (patch) | |
tree | 10b80c3905e06ecd885957ea2f333d9d8d705c56 | |
parent | a61a6b1db610a07060d0dcca54b66a4b2b3686cc (diff) |
Rework the video memory allocation.
The previous allocator worked in multiple passes, with (at least) one of
setting up allocations, another to attempt to adjust those for tiling, and
then a pass to set up the offsets and fix them in memory.
The new allocator is simpler, allocating memory immediately if possible,
setting up tiling up front, and choosing offsets immediately. AGP memory
is only allocated to back actual memory used, saving some memory that would
have been allocated for padding previous. It will also allow dynamic freeing
and reallocation of memory, which will be useful for framebuffer resizing.
-rw-r--r-- | src/i810_reg.h | 2 | ||||
-rw-r--r-- | src/i830.h | 175 | ||||
-rw-r--r-- | src/i830_accel.c | 12 | ||||
-rw-r--r-- | src/i830_cursor.c | 17 | ||||
-rw-r--r-- | src/i830_display.c | 6 | ||||
-rw-r--r-- | src/i830_dri.c | 42 | ||||
-rw-r--r-- | src/i830_driver.c | 441 | ||||
-rw-r--r-- | src/i830_exa.c | 5 | ||||
-rw-r--r-- | src/i830_memory.c | 2160 | ||||
-rw-r--r-- | src/i830_video.c | 23 | ||||
-rw-r--r-- | src/i830_xaa.c | 26 | ||||
-rw-r--r-- | src/i965_render.c | 4 |
12 files changed, 1162 insertions, 1751 deletions
diff --git a/src/i810_reg.h b/src/i810_reg.h index 455c226a..46d473d7 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -488,6 +488,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define I915G_FENCE_SIZE_32M 0x00000500 #define I915G_FENCE_SIZE_64M 0x00000600 #define I915G_FENCE_SIZE_128M 0x00000700 +#define I965_FENCE_X_MAJOR 0x00000000 +#define I965_FENCE_Y_MAJOR 0x00000002 #define FENCE_PITCH_1 0x00000000 #define FENCE_PITCH_2 0x00000010 #define FENCE_PITCH_4 0x00000020 @@ -113,30 +113,52 @@ typedef CARD8(*I830ReadIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr, typedef void (*I830WriteByteFunc)(I830Ptr pI830, IOADDRESS addr, CARD8 value); typedef CARD8(*I830ReadByteFunc)(I830Ptr pI830, IOADDRESS addr); -/* Linear region allocated in framebuffer. */ -typedef struct _I830MemPool *I830MemPoolPtr; -typedef struct _I830MemRange *I830MemRangePtr; -typedef struct _I830MemRange { - long Start; - long End; - long Size; - unsigned long Physical; - unsigned long Offset; /* Offset of AGP-allocated portion */ - unsigned long Alignment; - int Key; - I830MemPoolPtr Pool; -} I830MemRange; - -typedef struct _I830MemPool { - I830MemRange Total; - I830MemRange Free; - I830MemRange Fixed; - I830MemRange Allocated; -} I830MemPool; +/** Record of a linear allocation in the aperture. */ +typedef struct _i830_memory i830_memory; +struct _i830_memory { + /** Offset of the allocation in card VM */ + unsigned long offset; + /** End of the allocation in card VM */ + unsigned long end; + /** + * Requested size of the allocation: doesn't count padding. + * + * Any bound memory will cover offset to (offset + size). + */ + unsigned long size; + /** + * Physical (or more properly, bus) address of the allocation. + * Only set if requested during allocation. + */ + unsigned long bus_addr; + /** AGP memory handle */ + int key; + /** + * Whether or not the AGP memory (if any) is currently bound. + */ + Bool bound; + /** + * Offset that the AGP-allocated memory (if any) is to be bound to. + * + * This is either @offset or pI830->stolen_size + */ + unsigned long agp_offset; + + /** Description of the allocation, for logging */ + char *name; + + /** @{ + * Memory allocator linked list pointers + */ + i830_memory *next; + i830_memory *prev; + /** @} */ + +}; typedef struct { int tail_mask; - I830MemRange mem; + i830_memory *mem; unsigned char *virtual_start; int head; int tail; @@ -144,10 +166,6 @@ typedef struct { } I830RingBuffer; typedef struct { - unsigned int Fence[FENCE_NEW_NR * 2]; -} I830RegRec, *I830RegPtr; - -typedef struct { int lastInstance; int refCount; ScrnInfoPtr pScrn_1; @@ -206,8 +224,8 @@ typedef struct _I830CrtcPrivateRec { ExaOffscreenArea *rotate_mem_exa; #endif - I830MemRange cursor_mem; - I830MemRange cursor_mem_argb; + i830_memory *cursor_mem; + i830_memory *cursor_mem_argb; } I830CrtcPrivateRec, *I830CrtcPrivatePtr; #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private) @@ -249,36 +267,26 @@ typedef struct _I830Rec { /* These are set in PreInit and never changed. */ long FbMapSize; - long TotalVideoRam; - I830MemRange StolenMemory; /* pre-allocated memory */ - /* These change according to what has been allocated. */ - long FreeMemory; - I830MemRange MemoryAperture; - I830MemPool StolenPool; - long allocatedMemory; + i830_memory *memory_list; /**< Linked list of video memory allocations */ + long stolen_size; /**< bytes of pre-bound stolen memory */ + int gtt_acquired; /**< whether we currently own the AGP */ - /* Regions allocated either from the above pools, or from agpgart. */ - /* for single and dual head configurations */ - I830MemRange FrontBuffer; - I830MemRange FrontBuffer2; - I830MemRange Scratch; - I830MemRange Scratch2; + i830_memory *front_buffer; + i830_memory *front_buffer_2; + i830_memory *xaa_scratch; + i830_memory *xaa_scratch_2; #ifdef I830_USE_EXA - I830MemRange Offscreen; - I830MemRange EXAStateMem; /* specific exa state for G965 */ + i830_memory *exa_offscreen; + i830_memory *exa_965_state; #endif /* Regions allocated either from the above pools, or from agpgart. */ I830RingBuffer *LpRing; -#if REMAP_RESERVED - I830MemRange Dummy; -#endif - #ifdef I830_XV /* For Xvideo */ - I830MemRange *OverlayMem; - I830MemRange LinearMem; + i830_memory *overlay_regs; + i830_memory *xaa_linear; #endif unsigned long LinearAlloc; XF86ModReqInfo shadowReq; /* to test for later libshadow */ @@ -288,11 +296,13 @@ typedef struct _I830Rec { CreateScreenResourcesProcPtr CreateScreenResources; int *used3D; - I830MemRange ContextMem; + i830_memory *logical_context; #ifdef XF86DRI - I830MemRange BackBuffer; - I830MemRange DepthBuffer; - I830MemRange TexMem; + i830_memory *back_buffer; + i830_memory *depth_buffer; + i830_memory *textures; /**< Compatibility texture memory */ + i830_memory *memory_manager; /**< DRI memory manager aperture */ + int TexGranularity; int drmMinor; Bool have3DWindows; @@ -330,13 +340,21 @@ typedef struct _I830Rec { unsigned int BR[20]; - int GttBound; - unsigned char **ScanlineColorExpandBuffers; int NumScanlineColorExpandBuffers; int nextColorExpandBuf; - I830RegRec ModeReg; + /** + * Values to be programmed into the fence registers. + * + * Pre-965, this is a list of FENCE_NR (8) CARD32 registers that + * contain their start, size, and pitch. On the 965, it is a list of + * FENCE_NEW_NR CARD32s for the start and pitch fields (low 32 bits) of + * the fence registers followed by FENCE_NEW_NR CARD32s for the end fields + * (high 32 bits) of the fence registers. + */ + unsigned int fence[FENCE_NEW_NR * 2]; + unsigned int next_fence; Bool useEXA; Bool noAccel; @@ -407,7 +425,6 @@ typedef struct _I830Rec { /* Broken-out options. */ OptionInfoPtr Options; - /* Stolen memory support */ Bool StolenOnly; Bool swfSaved; @@ -499,7 +516,6 @@ typedef struct _I830Rec { } I830Rec; #define I830PTR(p) ((I830Ptr)((p)->driverPrivate)) -#define I830REGPTR(p) (&(I830PTR(p)->ModeReg)) #define I830_SELECT_FRONT 0 #define I830_SELECT_BACK 1 @@ -528,9 +544,6 @@ extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on); #ifdef XF86DRI extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags); -extern Bool I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags); -extern Bool I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags); -extern Bool I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags); extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn); extern Bool I830DRIScreenInit(ScreenPtr pScreen); extern Bool I830CheckDRIAvailable(ScrnInfoPtr pScrn); @@ -561,26 +574,17 @@ extern void I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, extern void I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h); -extern void I830ResetAllocations(ScrnInfoPtr pScrn, const int flags); +Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, + unsigned long size); +void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, + const char *prefix); +void i830_reset_allocations(ScrnInfoPtr pScrn); extern long I830CheckAvailableMemory(ScrnInfoPtr pScrn); -extern long I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn); -extern Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags); -extern Bool I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool); -extern Bool I830FixupOffsets(ScrnInfoPtr pScrn); -extern Bool I830BindAGPMemory(ScrnInfoPtr pScrn); -extern Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); -extern unsigned long I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, - I830MemPool *pool, long size, - unsigned long alignment, int flags); -extern void I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range); - -extern void I830PrintAllRegisters(I830RegPtr i830Reg); -extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg); - -extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer); +Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn, const int flags); +Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn, const int flags); + extern Bool I830IsPrimary(ScrnInfoPtr pScrn); -extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); @@ -607,6 +611,9 @@ extern void i830MarkSync(ScrnInfoPtr pScrn); extern void i830WaitSync(ScrnInfoPtr pScrn); /* i830_memory.c */ +Bool i830_bind_all_memory(ScrnInfoPtr pScrn); +Bool i830_unbind_all_memory(ScrnInfoPtr pScrn); + Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); #ifdef I830_USE_XAA @@ -656,18 +663,8 @@ extern const int I830PatternROP[16]; extern const int I830CopyROP[16]; /* Flags for memory allocation function */ -#define FROM_ANYWHERE 0x00000000 -#define FROM_POOL_ONLY 0x00000001 -#define FROM_NEW_ONLY 0x00000002 -#define FROM_MASK 0x0000000f - -#define ALLOCATE_AT_TOP 0x00000010 -#define ALLOCATE_AT_BOTTOM 0x00000020 -#define FORCE_GAPS 0x00000040 - -#define NEED_PHYSICAL_ADDR 0x00000100 -#define ALIGN_BOTH_ENDS 0x00000200 -#define FORCE_LOW 0x00000400 +#define NEED_PHYSICAL_ADDR 0x00000001 +#define ALIGN_BOTH_ENDS 0x00000002 #define ALLOC_NO_TILING 0x00001000 #define ALLOC_INITIAL 0x00002000 diff --git a/src/i830_accel.c b/src/i830_accel.c index db3168a8..49a9c134 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -117,7 +117,7 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) - ring->space += ring->mem.Size; + ring->space += ring->mem->size; iters++; now = GetTimeInMillis(); @@ -195,9 +195,9 @@ I830Sync(ScrnInfoPtr pScrn) ADVANCE_LP_RING(); } - I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0); + I830WaitLpRing(pScrn, pI830->LpRing->mem->size - 8, 0); - pI830->LpRing->space = pI830->LpRing->mem.Size - 8; + pI830->LpRing->space = pI830->LpRing->mem->size - 8; pI830->nextColorExpandBuf = 0; } @@ -226,10 +226,10 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int buffer) switch (buffer) { #ifdef XF86DRI case I830_SELECT_BACK: - pI830->bufferOffset = pI830->BackBuffer.Start; + pI830->bufferOffset = pI830->back_buffer->offset; break; case I830_SELECT_DEPTH: - pI830->bufferOffset = pI830->DepthBuffer.Start; + pI830->bufferOffset = pI830->depth_buffer->offset; break; #endif default: @@ -252,7 +252,7 @@ I830RefreshRing(ScrnInfoPtr pScrn) pI830->LpRing->tail = INREG(LP_RING + RING_TAIL); pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); if (pI830->LpRing->space < 0) - pI830->LpRing->space += pI830->LpRing->mem.Size; + pI830->LpRing->space += pI830->LpRing->mem->size; i830MarkSync(pScrn); } diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 70a8d52b..0cfd2292 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -88,20 +88,20 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc) I830Ptr pI830 = I830PTR(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE); - I830MemRange *cursor_mem; + i830_memory *cursor_mem; if (pipe >= xf86_config->num_crtc) FatalError("Bad pipe number for cursor base setting\n"); if (pI830->CursorIsARGB) - cursor_mem = &intel_crtc->cursor_mem_argb; + cursor_mem = intel_crtc->cursor_mem_argb; else - cursor_mem = &intel_crtc->cursor_mem; + cursor_mem = intel_crtc->cursor_mem; if (pI830->CursorNeedsPhysical) { - OUTREG(cursor_base, cursor_mem->Physical); + OUTREG(cursor_base, cursor_mem->bus_addr); } else { - OUTREG(cursor_base, cursor_mem->Start); + OUTREG(cursor_base, cursor_mem->offset); } } @@ -281,7 +281,7 @@ I830CRTCLoadCursorImage(xf86CrtcPtr crtc, unsigned char *src) ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem.Start); + CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem->offset); int x, y; DPRINTF(PFX, "I830LoadCursorImage\n"); @@ -372,7 +372,7 @@ static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) for (i = 0; i < xf86_config->num_crtc; i++) { I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; - if (!intel_crtc->cursor_mem_argb.Start) + if (!intel_crtc->cursor_mem_argb->offset) return FALSE; } @@ -389,7 +389,8 @@ static void I830CRTCLoadCursorARGB (xf86CrtcPtr crtc, CursorPtr pCurs) { I830Ptr pI830 = I830PTR(crtc->scrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem_argb.Start); + CARD32 *dst = (CARD32 *) (pI830->FbBase + + intel_crtc->cursor_mem_argb->offset); CARD32 *image = (CARD32 *)pCurs->bits->argb; int x, y, w, h; diff --git a/src/i830_display.c b/src/i830_display.c index 2e847051..a09d96ae 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -345,10 +345,10 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) if (crtc->rotatedData != NULL) { Start = (char *)crtc->rotatedData - (char *)pI830->FbBase; } else if (I830IsPrimary(pScrn)) { - Start = pI830->FrontBuffer.Start; + Start = pI830->front_buffer->offset; } else { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - Start = pI8301->FrontBuffer2.Start; + Start = pI8301->front_buffer_2->offset; } if (IS_I965G(pI830)) { @@ -1012,7 +1012,7 @@ i830_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height) "Couldn't allocate shadow memory for rotated CRTC\n"); return NULL; } - rotate_offset = pI830->FrontBuffer.Start + + rotate_offset = pI830->front_buffer->offset + intel_crtc->rotate_mem_xaa->offset * pI830->cpp; } #endif /* I830_USE_XAA */ diff --git a/src/i830_dri.c b/src/i830_dri.c index 70e7e491..9e3f3786 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -145,17 +145,17 @@ I830InitDma(ScrnInfoPtr pScrn) memset(&info, 0, sizeof(drmI830Init)); info.func = I830_INIT_DMA; - info.ring_start = ring->mem.Start + pI830->LinearAddr; - info.ring_end = ring->mem.End + pI830->LinearAddr; - info.ring_size = ring->mem.Size; + info.ring_start = ring->mem->offset + pI830->LinearAddr; + info.ring_end = ring->mem->end + pI830->LinearAddr; + info.ring_size = ring->mem->size; info.mmio_offset = (unsigned int)pI830DRI->regs; info.sarea_priv_offset = sizeof(XF86DRISAREARec); - info.front_offset = pI830->FrontBuffer.Start; - info.back_offset = pI830->BackBuffer.Start; - info.depth_offset = pI830->DepthBuffer.Start; + info.front_offset = pI830->front_buffer->offset; + info.back_offset = pI830->back_buffer->offset; + info.depth_offset = pI830->depth_buffer->offset; info.w = pScrn->virtualX; info.h = pScrn->virtualY; info.pitch = pI830->displayWidth; @@ -509,7 +509,7 @@ I830DRIScreenInit(ScreenPtr pScreen) pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL; #if 1 /* Remove this soon - see bug 5714 */ pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr + - pI830->FrontBuffer.Start; + pI830->front_buffer->offset; pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp); #else @@ -829,8 +829,8 @@ I830DRIDoMappings(ScreenPtr pScreen) (int)pI830DRI->regs); if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)pI830->LpRing->mem.Start + pI830->LinearAddr, - pI830->LpRing->mem.Size, DRM_AGP, 0, + (drm_handle_t)pI830->LpRing->mem->offset + pI830->LinearAddr, + pI830->LpRing->mem->size, DRM_AGP, 0, (drmAddress) &pI830->ring_map) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(ring_map) failed. Disabling DRI\n"); @@ -1325,10 +1325,10 @@ I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) OUT_RING(br13); OUT_RING((pbox->y1 << 16) | pbox->x1); OUT_RING((pbox->y2 << 16) | pbox->x2); - OUT_RING(pI830->BackBuffer.Start); + OUT_RING(pI830->back_buffer->offset); OUT_RING((pbox->y1 << 16) | pbox->x1); OUT_RING(br13 & 0xffff); - OUT_RING(pI830->FrontBuffer.Start); + OUT_RING(pI830->front_buffer->offset); ADVANCE_LP_RING(); } } @@ -1360,10 +1360,10 @@ I830EnablePageFlip(ScreenPtr pScreen) OUT_RING(br13); OUT_RING(0); OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX); - OUT_RING(pI830->BackBuffer.Start); + OUT_RING(pI830->back_buffer->offset); OUT_RING(0); OUT_RING(br13 & 0xffff); - OUT_RING(pI830->FrontBuffer.Start); + OUT_RING(pI830->front_buffer->offset); ADVANCE_LP_RING(); pSAREAPriv->pf_active = 1; @@ -1448,8 +1448,8 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) sarea->depth_tiled = pI830->depth_tiled; sarea->rotated_tiled = FALSE; - sarea->front_offset = pI830->FrontBuffer.Start; - /* Don't use FrontBuffer.Size here as it includes the pixmap cache area + 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 = pI830->displayWidth * pScrn->virtualY * pI830->cpp; @@ -1460,12 +1460,12 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) sarea->width = pScreen->width; sarea->height = pScreen->height; - sarea->back_offset = pI830->BackBuffer.Start; - sarea->back_size = pI830->BackBuffer.Size; - sarea->depth_offset = pI830->DepthBuffer.Start; - sarea->depth_size = pI830->DepthBuffer.Size; - sarea->tex_offset = pI830->TexMem.Start; - sarea->tex_size = pI830->TexMem.Size; + sarea->back_offset = pI830->back_buffer->offset; + sarea->back_size = pI830->back_buffer->size; + sarea->depth_offset = pI830->depth_buffer->offset; + sarea->depth_size = pI830->depth_buffer->size; + sarea->tex_offset = pI830->textures->offset; + sarea->tex_size = pI830->textures->size; sarea->log_tex_granularity = pI830->TexGranularity; sarea->pitch = pScrn->displayWidth; sarea->virtualX = pScrn->virtualX; diff --git a/src/i830_driver.c b/src/i830_driver.c index e46c0572..50fe2a6d 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -534,7 +534,7 @@ I830MapMem(ScrnInfoPtr pScrn) return FALSE; if (I830IsPrimary(pScrn)) - pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem.Start; + pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem->offset; return TRUE; } @@ -755,9 +755,6 @@ PreInitCleanup(ScrnInfoPtr pScrn) if (pI830->LpRing) xfree(pI830->LpRing); pI830->LpRing = NULL; - if (pI830->OverlayMem) - xfree(pI830->OverlayMem); - pI830->OverlayMem = NULL; if (pI830->overlayOn) xfree(pI830->overlayOn); pI830->overlayOn = NULL; @@ -836,6 +833,13 @@ I830ReduceMMSize(ScrnInfoPtr pScrn, unsigned long newSize, } #endif +/** + * This is called per zaphod head (so usually just once) to do initialization + * before the Screen is created. + * + * This code generally covers probing, module loading, option handling, + * initial memory layout measurement, card mapping, and RandR setup. + */ static Bool I830PreInit(ScrnInfoPtr pScrn, int flags) { @@ -846,12 +850,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; I830EntPtr pI830Ent = NULL; - int mem; + int sys_mem; int flags24; int i; char *s; pointer pVBEModule = NULL; - Bool enable; + Bool enable, allocation_done; const char *chipname; int num_pipe; int max_width, max_height; @@ -1187,41 +1191,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n", num_pipe, num_pipe > 1 ? "s" : ""); - /* - * Get the pre-allocated (stolen) memory size. - */ - pI830->StolenMemory.Size = I830DetectMemory(pScrn); - pI830->StolenMemory.Start = 0; - pI830->StolenMemory.End = pI830->StolenMemory.Size; - - /* Find the maximum amount of agpgart memory available. */ - if (I830IsPrimary(pScrn)) { - mem = I830CheckAvailableMemory(pScrn); - pI830->StolenOnly = FALSE; - } else { - /* videoRam isn't used on the second head, but faked */ - mem = pI830->entityPrivate->pScrn_1->videoRam; - pI830->StolenOnly = TRUE; - } - - if (mem <= 0) { - if (pI830->StolenMemory.Size <= 0) { - /* Shouldn't happen. */ - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "/dev/agpgart is either not available, or no memory " - "is available\nfor allocation, " - "and no pre-allocated memory is available.\n"); - PreInitCleanup(pScrn); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "/dev/agpgart is either not available, or no memory " - "is available\nfor allocation. " - "Using pre-allocated memory only.\n"); - mem = 0; - pI830->StolenOnly = TRUE; - } - if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) { pI830->noAccel = TRUE; } @@ -1358,8 +1327,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } RestoreHWState(pScrn); - pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; - /* XXX This should go away, replaced by xf86Crtc.c support for it */ pI830->rotation = RR_Rotate_0; @@ -1384,12 +1351,21 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } else pI830->checkDevices = FALSE; + pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; + + pI830->stolen_size = I830DetectMemory(pScrn); + /* * The "VideoRam" config file parameter specifies the maximum amount of * memory that will be used/allocated. When not present, we allow the * driver to allocate as much memory as it wishes to satisfy its - * allocations, but if agpgart support isn't available (StolenOnly == TRUE), - * it gets limited to the amount of pre-allocated ("stolen") memory. + * allocations, but if agpgart support isn't available, it gets limited + * to the amount of pre-allocated ("stolen") memory. + * + * Note that in using this value for allocator initialization, we're + * limiting aperture allocation to the VideoRam option, rather than limiting + * actual memory allocation, so alignment and things will cause less than + * VideoRam to be actually used. */ if (!pI830->pEnt->device->videoRam) { from = X_DEFAULT; @@ -1399,55 +1375,59 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam = pI830->pEnt->device->videoRam; } - /* Make sure it's on a page boundary */ - if (pScrn->videoRam & 3) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB " - "(page aligned - was %d KB)\n", - pScrn->videoRam & ~3, pScrn->videoRam); - pScrn->videoRam &= ~3; - } - - DPRINTF(PFX, - "Available memory: %dk\n" - "Requested memory: %dk\n", mem, pScrn->videoRam); - - - if (mem + (pI830->StolenMemory.Size / 1024) < pScrn->videoRam) { - pScrn->videoRam = mem + (pI830->StolenMemory.Size / 1024); - from = X_PROBED; - if (mem + (pI830->StolenMemory.Size / 1024) < - pI830->pEnt->device->videoRam) { + sys_mem = I830CheckAvailableMemory(pScrn); + if (sys_mem == -1) { + if (pScrn->videoRam > pI830->stolen_size / KB(1)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "VideoRAM reduced to %d kByte " - "(limited to available sysmem)\n", pScrn->videoRam); + "/dev/agpgart is either not available, or no memory " + "is available\nfor allocation. " + "Using pre-allocated memory only.\n"); + pScrn->videoRam = pI830->stolen_size / KB(1); + } + pI830->StolenOnly = TRUE; + } else { + if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) { + pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024); + from = X_PROBED; + if (sys_mem + (pI830->stolen_size / 1024) < + pI830->pEnt->device->videoRam) + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "VideoRAM reduced to %d kByte " + "(limited to available sysmem)\n", pScrn->videoRam); + } } } if (pScrn->videoRam > pI830->FbMapSize / 1024) { pScrn->videoRam = pI830->FbMapSize / 1024; - if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) + if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "VideoRam reduced to %d kByte (limited to aperture size)\n", + "VideoRam reduced to %d kByte (limited to aperture " + "size)\n", pScrn->videoRam); + } } - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Pre-allocated VideoRam: %ld kByte\n", - pI830->StolenMemory.Size / 1024); - xf86DrvMsg(pScrn->scrnIndex, from, "Potential VideoRam: %d kByte\n", - pScrn->videoRam); - - pI830->TotalVideoRam = KB(pScrn->videoRam); + /* Make sure it's on a page boundary */ + if (pScrn->videoRam & 3) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB " + "(page aligned - was %d KB)\n", + pScrn->videoRam & ~3, pScrn->videoRam); + pScrn->videoRam &= ~3; + } - /* - * If the requested videoRam amount is less than the stolen memory size, - * reduce the stolen memory size accordingly. - */ - if (pI830->StolenMemory.Size > pI830->TotalVideoRam) { - pI830->StolenMemory.Size = pI830->TotalVideoRam; - pI830->StolenMemory.End = pI830->TotalVideoRam; + if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't initialize video memory allocator\n"); + PreInitCleanup(pScrn); + return FALSE; } + xf86DrvMsg(pScrn->scrnIndex, + pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT, + "VideoRam: %d KB\n", pScrn->videoRam); + if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES, &(pI830->CacheLines))) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n", @@ -1502,12 +1482,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Alloc our pointers for the primary head */ if (I830IsPrimary(pScrn)) { - pI830->LpRing = xalloc(sizeof(I830RingBuffer)); - pI830->OverlayMem = xalloc(sizeof(I830MemRange)); + pI830->LpRing = xcalloc(1, sizeof(I830RingBuffer)); pI830->overlayOn = xalloc(sizeof(Bool)); pI830->used3D = xalloc(sizeof(int)); - if (!pI830->LpRing || - !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) { + if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not allocate primary data structures.\n"); PreInitCleanup(pScrn); @@ -1527,9 +1505,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (IS_I965G(pI830)) pI830->CursorNeedsPhysical = FALSE; - /* Force ring buffer to be in low memory for all chipsets */ - pI830->NeedRingBufferLow = TRUE; - /* * XXX If we knew the pre-initialised GTT format for certain, we could * probably figure out the physical address even in the StolenOnly case. @@ -1548,21 +1523,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->SWCursor = TRUE; } - /* - * Reduce the maximum videoram available for video modes by the ring buffer, - * minimum scratch space and HW cursor amounts. - */ - if (!pI830->SWCursor) { - pScrn->videoRam -= (HWCURSOR_SIZE / 1024); - pScrn->videoRam -= (HWCURSOR_SIZE_ARGB / 1024); - } - if (!pI830->XvDisabled) - pScrn->videoRam -= (OVERLAY_SIZE / 1024); - if (!pI830->noAccel) { - pScrn->videoRam -= (PRIMARY_RINGBUFFER_SIZE / 1024); - pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024); - } - if (!xf86RandR12PreInit (pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); @@ -1579,23 +1539,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->disableTiling = FALSE; +#if defined(XF86DRI) /* * If DRI is potentially usable, check if there is enough memory available * for it, and if there's also enough to allow tiling to be enabled. */ -#if defined(XF86DRI) if (!I830CheckDRIAvailable(pScrn)) { pI830->directRenderingDisabled = TRUE; pI830->mmSize = 0; - } else if (pScrn->videoRam > pI830->FbMapSize / 1024 - pI830->mmSize) { - I830ReduceMMSize(pScrn, pI830->FbMapSize - KB(pScrn->videoRam), - "to make room for video memory"); } if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) { int savedDisplayWidth = pScrn->displayWidth; - int memNeeded = 0; Bool tiled = FALSE; #ifdef I830_XV @@ -1612,12 +1568,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) ~(tile_pixels - 1); tiled = TRUE; } else { - /* Good pitches to allow tiling. Don't care about pitches < 1024. */ + /* Good pitches to allow tiling. Don't care about pitches < 1024 + * pixels. + */ static const int pitches[] = { - KB(1), - KB(2), - KB(4), - KB(8), + 1024, + 2048, + 4096, + 8192, 0 }; @@ -1630,120 +1588,72 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } + allocation_done = FALSE; /* * If the displayWidth is a tilable pitch, test if there's enough * memory available to enable tiling. */ savedMMSize = pI830->mmSize; if (tiled) { - retry_dryrun: - I830ResetAllocations(pScrn, 0); - if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) && - I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN)) { - memNeeded = I830GetExcessMemoryAllocations(pScrn); - if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) { - if (memNeeded > 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "%d kBytes additional video memory is " - "required to\n\tenable tiling mode for DRI.\n", - (memNeeded + 1023) / 1024); - } - if (pI830->MemoryAperture.Size < 0) { - if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) { - I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE, - "to make room in AGP aperture for tiling."); - goto retry_dryrun; - } - /* XXX */ - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Allocation with DRI tiling enabled would " - "exceed the\n" - "\tmemory aperture size (%ld kB) by %ld kB.\n" - "\tReduce VideoRam amount to avoid this!\n", - pI830->FbMapSize / 1024, - -pI830->MemoryAperture.Size / 1024); - } - pScrn->displayWidth = savedDisplayWidth; - pI830->allowPageFlip = FALSE; - } else if (pScrn->displayWidth != savedDisplayWidth) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Increasing the scanline pitch to allow tiling mode " - "(%d -> %d).\n", - savedDisplayWidth, pScrn->displayWidth); +retry_dryrun: + i830_reset_allocations(pScrn); + if (!i830_allocate_2d_memory(pScrn, + ALLOCATE_DRY_RUN | ALLOC_INITIAL) || + !i830_allocate_3d_memory(pScrn, ALLOCATE_DRY_RUN)) + { + /* Failure to set up allocations, so try reducing the DRI memory + * manager's size if we haven't yet. + */ + if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) { + I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE, + "to make room for tiling."); + goto retry_dryrun; } - } else { - memNeeded = 0; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Unexpected dry run allocation failure (1).\n"); + /* Otherwise, disable tiling. */ + pScrn->displayWidth = savedDisplayWidth; + pI830->allowPageFlip = FALSE; + } else if (pScrn->displayWidth != savedDisplayWidth) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Increasing the scanline pitch to allow tiling mode " + "(%d -> %d).\n", + savedDisplayWidth, pScrn->displayWidth); + allocation_done = TRUE; } } - if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) { + if (!allocation_done) { /* * Tiling can't be enabled. Check if there's enough memory for DRI * without tiling. */ pI830->mmSize = savedMMSize; pI830->disableTiling = TRUE; - retry_dryrun2: - I830ResetAllocations(pScrn, 0); - if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) && - I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_NO_TILING)) { - memNeeded = I830GetExcessMemoryAllocations(pScrn); - if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) { - if (memNeeded > 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "%d kBytes additional video memory is required " - "to enable DRI.\n", - (memNeeded + 1023) / 1024); - } - if (pI830->MemoryAperture.Size < 0) { - if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) { - I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE, - "to save AGP aperture space for video memory."); - goto retry_dryrun2; - } - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Allocation with DRI enabled would " - "exceed the\n" - "\tmemory aperture size (%ld kB) by %ld kB.\n" - "\tReduce VideoRam amount to avoid this!\n", - pI830->FbMapSize / 1024, - -pI830->MemoryAperture.Size / 1024); - } - pI830->mmSize = 0; - pI830->directRenderingDisabled = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n"); +retry_dryrun2: + i830_reset_allocations(pScrn); + if (!i830_allocate_2d_memory(pScrn, + ALLOCATE_DRY_RUN | ALLOC_INITIAL) || + !i830_allocate_3d_memory(pScrn, ALLOCATE_DRY_RUN)) + { + /* Failure to set up allocations, so try reducing the DRI memory + * manager's size if we haven't yet. + */ + if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) { + I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE, + "to save AGP aperture space for video " + "memory."); + goto retry_dryrun2; } - } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Unexpected dry run allocation failure (2).\n"); + "Not enough video memory. Disabling DRI."); + pI830->mmSize = 0; + pI830->directRenderingDisabled = TRUE; + } else { + allocation_done = TRUE; } } } else #endif pI830->disableTiling = TRUE; /* no DRI - so disableTiling */ - if (pI830->pEnt->device->videoRam == 0) { - int default_videoram; - - /* Now that we've sized the allocations, reduce our default VideoRam - * allocation from the aperture size to just what we need to cover our - * allocations. Only, put in some slop for alignment and such. - */ - default_videoram = pI830->StolenPool.Total.Size + pI830->allocatedMemory; - default_videoram += KB(512); /* slop */ - /* align to 1MB increments */ - default_videoram = (default_videoram + MB(1) - 1) / MB(1) * MB(1); - - if (default_videoram < KB(pScrn->videoRam)) { - pScrn->videoRam = default_videoram / KB(1); - pI830->TotalVideoRam = KB(pScrn->videoRam); - } - } - xf86DrvMsg(pScrn->scrnIndex, - pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT, - "VideoRam: %d KB\n", pScrn->videoRam); - if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support DRI with frame buffer width > 2048.\n"); @@ -1934,18 +1844,18 @@ SetFenceRegs(ScrnInfoPtr pScrn) if (IS_I965G(pI830)) { for (i = 0; i < FENCE_NEW_NR; i++) { - OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]); - OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]); + OUTREG(FENCE_NEW + i * 8, pI830->fence[i]); + OUTREG(FENCE_NEW + 4 + i * 8, pI830->fence[i+FENCE_NEW_NR]); if (I810_DEBUG & DEBUG_VERBOSE_VGA) { - ErrorF("Fence Start Register : %x\n", pI830->ModeReg.Fence[i]); - ErrorF("Fence End Register : %x\n", pI830->ModeReg.Fence[i+FENCE_NEW_NR]); + ErrorF("Fence Start Register : %x\n", pI830->fence[i]); + ErrorF("Fence End Register : %x\n", pI830->fence[i+FENCE_NEW_NR]); } } } else { for (i = 0; i < FENCE_NR; i++) { - OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]); + OUTREG(FENCE + i * 4, pI830->fence[i]); if (I810_DEBUG & DEBUG_VERBOSE_VGA) - ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]); + ErrorF("Fence Register : %x\n", pI830->fence[i]); } } } @@ -1970,25 +1880,22 @@ SetRingRegs(ScrnInfoPtr pScrn) OUTREG(LP_RING + RING_TAIL, 0); OUTREG(LP_RING + RING_HEAD, 0); - if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) != - pI830->LpRing->mem.Start) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "I830SetRingRegs: Ring buffer start (%lx) violates its " - "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK); - } + assert((pI830->LpRing->mem->offset & I830_RING_START_MASK) == + pI830->LpRing->mem->offset); + /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK; + itemp = pI830->LpRing->mem->offset; OUTREG(LP_RING + RING_START, itemp); - if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) != - pI830->LpRing->mem.Size - 4096) { + if (((pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES) != + pI830->LpRing->mem->size - 4096) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its " - "mask (%x)\n", pI830->LpRing->mem.Size - 4096, + "mask (%x)\n", pI830->LpRing->mem->size - 4096, I830_RING_NR_PAGES); } /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES; + itemp = (pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES; itemp |= (RING_NO_REPORT | RING_VALID); OUTREG(LP_RING + RING_LEN, itemp); I830RefreshRing(pScrn); @@ -2246,13 +2153,12 @@ static void InitRegisterRec(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - I830RegPtr i830Reg = &pI830->ModeReg; int i; if (!I830IsPrimary(pScrn)) return; for (i = 0; i < 8; i++) - i830Reg->Fence[i] = 0; + pI830->fence[i] = 0; } static void @@ -2361,14 +2267,12 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn) } #endif - ctx_addr = pI830->ContextMem.Start; - /* Align to a 2k boundry */ - ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048; - + ctx_addr = pI830->logical_context->offset; + assert((pI830->logical_context->offset & 2047) == 0); { BEGIN_LP_RING(2); OUT_RING(MI_SET_CONTEXT); - OUT_RING(ctx_addr | + OUT_RING(pI830->logical_context->offset | CTXT_NO_RESTORE | CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE); ADVANCE_LP_RING(); @@ -2525,14 +2429,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (I830IsPrimary(pScrn)) { if (!pI830->LpRing) pI830->LpRing = xalloc(sizeof(I830RingBuffer)); - if (!pI830->OverlayMem) - pI830->OverlayMem = xalloc(sizeof(I830MemRange)); if (!pI830->overlayOn) pI830->overlayOn = xalloc(sizeof(Bool)); if (!pI830->used3D) pI830->used3D = xalloc(sizeof(int)); - if (!pI830->LpRing || - !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) { + if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not allocate primary data structures.\n"); return FALSE; @@ -2546,7 +2447,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!I830IsPrimary(pScrn)) { pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); pI830->LpRing = pI8301->LpRing; - pI830->OverlayMem = pI8301->OverlayMem; + pI830->overlay_regs = pI8301->overlay_regs; pI830->overlayOn = pI8301->overlayOn; pI830->used3D = pI8301->used3D; } @@ -2579,14 +2480,14 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #endif if (I830IsPrimary(pScrn)) { - I830ResetAllocations(pScrn, 0); + i830_reset_allocations(pScrn); - if (!I830Allocate2DMemory(pScrn, ALLOC_INITIAL)) + if (!i830_allocate_2d_memory(pScrn, ALLOC_INITIAL)) return FALSE; } if (!pI830->noAccel) { - if (pI830->LpRing->mem.Size == 0) { + if (pI830->LpRing->mem->size == 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling acceleration because the ring buffer " "allocation failed.\n"); @@ -2601,7 +2502,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) "needs 2D acceleration.\n"); pI830->XvEnabled = FALSE; } - if (pI830->OverlayMem->Physical == 0) { + if (pI830->overlay_regs == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because the overlay register buffer " "allocation failed.\n"); @@ -2639,8 +2540,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (pI830->directRenderingEnabled) { pI830->directRenderingEnabled = - I830Allocate3DMemory(pScrn, - pI830->disableTiling ? ALLOC_NO_TILING : 0); + i830_allocate_3d_memory(pScrn, + pI830->disableTiling ? ALLOC_NO_TILING : 0); if (!pI830->directRenderingEnabled) I830DRICloseScreen(pScreen); } @@ -2649,27 +2550,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->directRenderingEnabled = FALSE; #endif - /* + /* XXX: * After the 3D allocations have been done, see if there's any free space * that can be added to the framebuffer allocation. */ if (I830IsPrimary(pScrn)) { - I830Allocate2DMemory(pScrn, 0); - - DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n"); - if (!I830DoPoolAllocation(pScrn, &(pI830->StolenPool))) - return FALSE; - - DPRINTF(PFX, "assert( if(!I830FixupOffsets(pScrn)) )\n"); - if (!I830FixupOffsets(pScrn)) - return FALSE; + i830_allocate_2d_memory(pScrn, 0); } + i830_describe_allocations(pScrn, 1, ""); #ifdef XF86DRI - if (pI830->directRenderingEnabled) { - I830SetupMemoryTiling(pScrn); + if (pI830->directRenderingEnabled) pI830->directRenderingEnabled = I830DRIDoMappings(pScreen); - } #endif DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n"); @@ -2679,9 +2571,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScrn->memPhysBase = (unsigned long)pI830->FbBase; if (I830IsPrimary(pScrn)) { - pScrn->fbOffset = pI830->FrontBuffer.Start; + pScrn->fbOffset = pI830->front_buffer->offset; } else { - pScrn->fbOffset = pI8301->FrontBuffer2.Start; + pScrn->fbOffset = pI8301->front_buffer_2->offset; } pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth; @@ -2704,13 +2596,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, - pI830->LinearMem.Offset / pI830->cpp, - pI830->LinearMem.Size / pI830->cpp)) + pI830->xaa_linear->offset / pI830->cpp, + pI830->xaa_linear->size / pI830->cpp)) { xf86DrvMsg(scrnIndex, X_INFO, "Using %ld bytes of offscreen memory for linear " - "(offset=0x%lx)\n", pI830->LinearMem.Size, - pI830->LinearMem.Offset); + "(offset=0x%lx)\n", pI830->xaa_linear->size, + pI830->xaa_linear->offset); } } else { if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { @@ -2877,27 +2769,24 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->suspended = FALSE; #ifdef XF86DRI_MM - if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) { - unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) - / GTT_PAGE_SIZE; - unsigned long aperStart = ROUND_TO(pI830->FbMapSize - KB(pI830->mmSize), GTT_PAGE_SIZE) - / GTT_PAGE_SIZE; - - if (aperEnd < aperStart || aperEnd - aperStart < I830_MM_MINPAGES) { + 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" - "\tor decrease the amount of video RAM using option \"VideoRam\".\n" + "\tPlease increase AGP aperture size from BIOS configuration screen.\n" "\tDisabling DRI.\n"); pI830->directRenderingOpen = FALSE; I830DRICloseScreen(pScreen); pI830->directRenderingEnabled = FALSE; } else { #ifndef XSERVER_LIBDRM_MM - if (I830DrmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart, + if (I830DrmMMInit(pI830->drmSubFD, pI830->memory_manager->offset, + pI830->memory_manager->size, DRM_BO_MEM_TT)) { #else - if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart, + if (drmMMInit(pI830->drmSubFD, pI830->memory_manager->offset, + pI830->memory_manager->size, DRM_BO_MEM_TT)) { #endif xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -2906,12 +2795,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->directRenderingOpen = FALSE; I830DRICloseScreen(pScreen); pI830->directRenderingEnabled = FALSE; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Initialized DRM memory manager, %ld AGP pages\n" - "\tat AGP offset 0x%lx\n", - aperEnd - aperStart, - aperStart); } } } @@ -2968,7 +2851,7 @@ I830LeaveVT(int scrnIndex, int flags) if (!I830IsPrimary(pScrn)) { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - if (!pI8301->GttBound) { + if (!pI8301->gtt_acquired) { return; } } @@ -3002,7 +2885,7 @@ I830LeaveVT(int scrnIndex, int flags) i830DumpRegs (pScrn); if (I830IsPrimary(pScrn)) - I830UnbindAGPMemory(pScrn); + i830_unbind_all_memory(pScrn); if (pI830->AccelInfoRec) pI830->AccelInfoRec->NeedToSync = FALSE; } @@ -3038,7 +2921,7 @@ I830EnterVT(int scrnIndex, int flags) #endif if (I830IsPrimary(pScrn)) - if (!I830BindAGPMemory(pScrn)) + if (!i830_bind_all_memory(pScrn)) return FALSE; if (i830_check_error_state(pScrn)) { @@ -3223,8 +3106,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) xfree(pI830->LpRing); pI830->LpRing = NULL; - xfree(pI830->OverlayMem); - pI830->OverlayMem = NULL; xfree(pI830->overlayOn); pI830->overlayOn = NULL; xfree(pI830->used3D); diff --git a/src/i830_exa.c b/src/i830_exa.c index 42552d44..37fd2842 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -318,8 +318,9 @@ I830EXAInit(ScreenPtr pScreen) pI830->EXADriverPtr->exa_major = 2; pI830->EXADriverPtr->exa_minor = 1; pI830->EXADriverPtr->memoryBase = pI830->FbBase; - pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start; - pI830->EXADriverPtr->memorySize = pI830->Offscreen.End; + pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset; + pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset + + pI830->exa_offscreen->size; DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n", pI830->EXADriverPtr->memoryBase, diff --git a/src/i830_memory.c b/src/i830_memory.c index 1b2af120..93429fba 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -50,6 +50,51 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Alan Hourihane <alanh@tungstengraphics.com> */ +/** + * @file i830_memory.c + * + * This is the video memory allocator. Our memory allocation is different from + * other graphics chips, where you have a fixed amount of graphics memory + * available that you want to put to the best use. Instead, we have almost no + * memory pre-allocated, and we have to choose an appropriate amount of sytem + * memory to use. + * + * The allocations we might do: + * + * - Ring buffer + * - HW cursor 1 + * - HW cursor 2 + * - HW ARGB cursor 1 + * - HW ARGB cursor 2 + * - Overlay registers + * - XAA linear allocator (optional) + * - EXA 965 state buffer + * - XAA scratch (screen 1) + * - XAA scratch (screen 2, only in zaphod mode) + * - Front buffer (screen 1, more is better for XAA) + * - Front buffer (screen 2, only in zaphod mode, more is better for XAA) + * - Back/depth buffer (3D only) + * - Compatibility texture pool (optional, more is always better) + * - New texture pool (optional, more is always better. aperture allocation + * only) + * - EXA offscreen pool (more is always better) + * + * We also want to be able to resize the front/back/depth buffers, and then + * resize the EXA and texture memory pools appropriately. + * + * The user may request a specific amount of memory to be used + * (pI830->pEnt->videoRam != 0), in which case allocations have to fit within + * that much aperture. If not, the individual allocations will be + * automatically sized, and will be fit within the maximum aperture size. + * Only the actual memory used (not alignment padding) will get actual AGP + * memory allocated. + * + * Given that the allocations listed are generally a page or more than a page, + * our allocator will only return page-aligned offsets, simplifying the memory + * binding process. For smaller allocations, the acceleration architecture's + * linear allocator is preferred. + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -62,383 +107,541 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i810_reg.h" -static int nextTile = 0; -static unsigned int tileGeneration = -1; +#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) + +enum tile_format { + TILING_NONE, + TILING_XMAJOR, + TILING_YMAJOR +}; + +static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset, + unsigned int pitch, unsigned int size, + enum tile_format tile_format); +/** + * Returns the fence size for a tiled area of the given size. + */ static unsigned long -GetBestTileAlignment(unsigned long size) +i830_get_fence_size(ScrnInfoPtr pScrn, unsigned long size) { + I830Ptr pI830 = I830PTR(pScrn); unsigned long i; + unsigned long start; - for (i = KB(512); i < size; i <<= 1) - ; + if (IS_I965G(pI830)) { + /* The 965 can have fences at any page boundary. */ + return ALIGN(size, GTT_PAGE_SIZE); + } else { + /* Align the size to a power of two greater than the smallest fence + * size. + */ + if (IS_I9XX(pI830)) + start = MB(1); + else + start = KB(512); - if (i > MB(64)) - i = MB(64); + for (i = start; i < size; i <<= 1) + ; - return i; + return i; + } } -/* - * Allocate memory from the given pool. Grow the pool if needed and if - * possible. - */ -static unsigned long -AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool, - long size, unsigned long alignment, int flags) +static Bool +i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem) { I830Ptr pI830 = I830PTR(pScrn); - long needed, start, end; - Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - if (!result || !pool || !size) - return 0; - - /* Calculate how much space is needed. */ - if (alignment <= GTT_PAGE_SIZE) - needed = size; - else { - if (flags & ALLOCATE_AT_BOTTOM) { - start = ROUND_TO(pool->Free.Start, alignment); - if (flags & ALIGN_BOTH_ENDS) - end = ROUND_TO(start + size, alignment); - else - end = start + size; - needed = end - pool->Free.Start; - } else { /* allocate at top */ - if (flags & ALIGN_BOTH_ENDS) - end = ROUND_DOWN_TO(pool->Free.End, alignment); - else - end = pool->Free.End; - - start = ROUND_DOWN_TO(end - size, alignment); - needed = end - start; - } + if (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired) + return TRUE; + + if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) { + mem->bound = TRUE; + return TRUE; + } else { + return FALSE; } - if (needed > pool->Free.Size) { - long extra; - /* See if the pool can be grown. */ - if (pI830->StolenOnly && !dryrun) - return 0; - extra = needed - pool->Free.Size; - extra = ROUND_TO_PAGE(extra); - if (extra > pI830->FreeMemory) { - if (dryrun) - pI830->FreeMemory = extra; - else - return 0; - } - if (!dryrun && ((long)extra > pI830->MemoryAperture.Size)) - return 0; + return TRUE; +} - pool->Free.Size += extra; - pool->Free.End += extra; - pool->Total.Size += extra; - pool->Total.End += extra; - pI830->FreeMemory -= extra; - pI830->MemoryAperture.Start += extra; - pI830->MemoryAperture.Size -= extra; - } - if (flags & ALLOCATE_AT_BOTTOM) { - result->Start = ROUND_TO(pool->Free.Start, alignment); - pool->Free.Start += needed; - result->End = pool->Free.Start; +static Bool +i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem) +{ + if (mem == NULL || mem->key == -1 || !mem->bound) + return TRUE; + + if (xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) { + mem->bound = FALSE; + return TRUE; } else { - result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment); - pool->Free.End -= needed; - result->End = result->Start + needed; + return FALSE; } - pool->Free.Size = pool->Free.End - pool->Free.Start; - result->Size = result->End - result->Start; - result->Pool = pool; - result->Alignment = alignment; - return needed; } -static unsigned long -AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, long size, - unsigned long alignment, int flags) +static void +i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem) +{ + i830_unbind_memory(pScrn, mem); + + /* 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; + } + + xfree(mem->name); + xfree(mem); +} + +/* Resets the state of the aperture allocator, freeing all memory that had + * been allocated. + */ +void +i830_reset_allocations(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - unsigned long start, end; - unsigned long newApStart, newApEnd; - Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - if (!result || !size) - return 0; + /* While there is any memory between the start and end markers, free it. */ + while (pI830->memory_list->next->next != NULL) + i830_free_memory(pScrn, pI830->memory_list->next); - if ((flags & ALLOCATE_AT_BOTTOM) && pI830->StolenMemory.Size != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "AllocFromAGP(): can't allocate from " - "bottom when there is stolen memory\n"); - return 0; + /* Null out the pointers for all the allocations we just freed. This is + * kind of gross, but at least it's just one place now. + */ + for (i = 0; i < xf86_config->num_crtc; i++) { + I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; + + intel_crtc->cursor_mem = NULL; + intel_crtc->cursor_mem_argb = NULL; } - if (size > pI830->FreeMemory) { - if (dryrun) - pI830->FreeMemory = size; - else - return 0; + pI830->front_buffer = NULL; + pI830->front_buffer_2 = NULL; + pI830->xaa_scratch = NULL; + pI830->xaa_scratch_2 = NULL; + pI830->exa_offscreen = NULL; + pI830->exa_965_state = NULL; + pI830->overlay_regs = NULL; + pI830->xaa_linear = NULL; + pI830->logical_context = NULL; + pI830->back_buffer = NULL; + pI830->depth_buffer = NULL; + pI830->textures = NULL; + pI830->memory_manager = NULL; + pI830->LpRing->mem = NULL; +} + +/** + * Initialize's the driver's video memory allocator to allocate in the + * given range. + */ +Bool +i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, + unsigned long size) +{ + I830Ptr pI830 = I830PTR(pScrn); + i830_memory *start, *end; + + start = xcalloc(1, sizeof(*start)); + if (start == NULL) + return FALSE; + start->name = xstrdup("start marker"); + if (start->name == NULL) { + xfree(start); + return FALSE; + } + end = xcalloc(1, sizeof(*end)); + if (end == NULL) { + xfree(start->name); + xfree(start); + return FALSE; + } + end->name = xstrdup("end marker"); + if (end->name == NULL) { + xfree(start->name); + xfree(start); + xfree(end); + return FALSE; } - /* Calculate offset */ - if (flags & ALLOCATE_AT_BOTTOM) { - start = ROUND_TO(pI830->MemoryAperture.Start, alignment); - if (flags & ALIGN_BOTH_ENDS) - end = ROUND_TO(start + size, alignment); - else - end = start + size; - newApStart = end; - newApEnd = pI830->MemoryAperture.End; - } else { + start->key = -1; + start->offset = offset; + start->end = start->offset; + start->size = 0; + start->next = end; + end->key = -1; + end->offset = offset + size; + end->end = end->offset; + end->size = 0; + end->prev = start; + + pI830->memory_list = start; + + return TRUE; +} + +/* Allocate aperture space for the given size and alignment, and returns the + * memory allocation. + * + * Allocations are a minimum of a page, and will be at least page-aligned. + */ +static i830_memory * +i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name, + long size, unsigned long alignment, int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + i830_memory *mem, *scan; + + mem = xcalloc(1, sizeof(*mem)); + if (mem == NULL) + return NULL; + + /* No memory allocated to back the region */ + mem->key = -1; + + mem->name = xstrdup(name); + if (mem->name == NULL) { + xfree(mem); + return NULL; + } + mem->size = size; + + if (alignment < GTT_PAGE_SIZE) + alignment = GTT_PAGE_SIZE; + + for (scan = pI830->memory_list; scan->next != NULL; scan = scan->next) { + mem->offset = ROUND_TO(scan->end, alignment); + mem->end = mem->offset + size; if (flags & ALIGN_BOTH_ENDS) - end = ROUND_DOWN_TO(pI830->MemoryAperture.End, alignment); - else - end = pI830->MemoryAperture.End; - start = ROUND_DOWN_TO(end - size, alignment); - newApStart = pI830->MemoryAperture.Start; - newApEnd = start; + mem->end = ROUND_TO(mem->end, alignment); + if (mem->end <= scan->next->offset) + break; + } + if (scan->next == NULL) { + /* Reached the end of the list, and didn't find space */ + xfree(mem->name); + xfree(mem); + return NULL; } + /* Insert new allocation into the list */ + mem->prev = scan; + mem->next = scan->next; + scan->next = mem; + mem->next->prev = scan; - if (!dryrun) { - if (newApStart > newApEnd) - return 0; + return mem; +} - if (flags & NEED_PHYSICAL_ADDR) { - result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, - &(result->Physical)); - } else { - result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, - NULL); - } +/** + * Allocates the AGP memory necessary for the part of a memory allocation not + * already covered by the stolen memory. + * + * The memory is automatically bound if we have the VT. + */ +static Bool +i830_allocate_agp_memory(ScrnInfoPtr pScrn, i830_memory *mem, int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long size; + + if (mem->key != -1) + return TRUE; + + if (mem->offset + mem->size <= pI830->stolen_size) + return TRUE; + + if (mem->offset < pI830->stolen_size) + mem->agp_offset = pI830->stolen_size; + else + mem->agp_offset = mem->offset; + + size = mem->size - (mem->agp_offset - mem->offset); - if (result->Key == -1) - return 0; + if (flags & NEED_PHYSICAL_ADDR) + mem->key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, + &mem->bus_addr); + else + mem->key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL); + if (mem->key == -1 || ((flags & NEED_PHYSICAL_ADDR) && mem->bus_addr == 0)) + { + return FALSE; + } + + if (!i830_bind_memory(pScrn, mem)) { + return FALSE; } - pI830->allocatedMemory += size; - pI830->MemoryAperture.Start = newApStart; - pI830->MemoryAperture.End = newApEnd; - pI830->MemoryAperture.Size = newApEnd - newApStart; - pI830->FreeMemory -= size; - result->Start = start; - result->End = start + size; - result->Size = size; - result->Offset = start; - result->Alignment = alignment; - result->Pool = NULL; - - return size; + return TRUE; } -void -I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range) + +/* Allocates video memory at the given size and alignment. + * + * The memory will be bound automatically when the driver is in control of the + * VT. + */ +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; - if (!range || range->Size == 0) - return; + mem = i830_allocate_aperture(pScrn, name, size, alignment, flags); + if (mem == NULL) + return NULL; - if (range->Key != -1) - xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key); + if (!i830_allocate_agp_memory(pScrn, mem, flags)) { + i830_free_memory(pScrn, mem); + return NULL; + } - if (range->Pool) { - /* - * This code essentially resets what I830DoPoolAllocation() did. - * And if things are freed in the wrong order this can break wildly! - * USE CAUTION when changing anything here... - */ - I830MemPool *Pool = range->Pool; - Pool->Total.End = pI830->StolenMemory.End; + return mem; +} - if (pI830->StolenOnly) - Pool->Free.End += range->Size; - else - Pool->Free.End = Pool->Total.End; +/* Allocate a tiled region with the given size and pitch. + * + * As is, we might miss out on tiling some allocations on older hardware with + * large framebuffer size and a small aperture size, where the first + * allocations use a large alignment even though we've got fences to spare, and + * the later allocations can't find enough aperture space left. We could do + * some search across all allocation options to fix this, probably, but that + * would be another rewrite. + */ +static i830_memory * +i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name, + unsigned long size, unsigned long pitch, + unsigned long alignment, int flags, + enum tile_format tile_format) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long aper_size; + unsigned long aper_align; + i830_memory *mem; + int fence_divide, i; - if (Pool->Free.End < Pool->Free.Start) { - Pool->Free.End = Pool->Free.Start; - } + if (tile_format == TILING_NONE) + return i830_allocate_memory(pScrn, name, size, alignment, flags); - Pool->Free.Size = Pool->Free.End - Pool->Free.Start; - Pool->Total.Size = Pool->Total.End - Pool->Total.Start; + /* Check for maximum tiled region size */ + if (IS_I9XX(pI830)) { + if (size > MB(128)) + return NULL; + } else { + if (size > MB(64)) + return NULL; + } - if (!pI830->StolenOnly) { - pI830->FreeMemory -= Pool->Free.Size; - pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size); - pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size); - } + aper_size = i830_get_fence_size(pScrn, size); + if (IS_I965G(pI830)) { + aper_align = GTT_PAGE_SIZE; } else { - if (range->Alignment == GTT_PAGE_SIZE) - pI830->MemoryAperture.End = range->End; - else { - pI830->MemoryAperture.End = range->End - range->Size + - range->Alignment; + /* The offset has to be aligned to at least the size of the fence + * region. + */ + aper_align = aper_size; + } + if (aper_align < alignment) + aper_align = alignment; + + fence_divide = 1; + mem = i830_allocate_aperture(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 + * alignment requirements and using more fences to cover the area. + */ + for (fence_divide = 2; fence_divide <= 4 && mem == NULL; + fence_divide *= 2) + { + /* Check that it's not too small for fencing. */ + if (i830_get_fence_size(pScrn, aper_align / fence_divide) != + aper_align / fence_divide) + { + break; + } + + mem = i830_allocate_aperture(pScrn, name, aper_size, + aper_align / fence_divide, flags); } - pI830->MemoryAperture.Size = pI830->MemoryAperture.End - - pI830->MemoryAperture.Start; } - if (!pI830->StolenOnly) - pI830->FreeMemory += range->Size; - pI830->allocatedMemory -= range->Size; + if (mem == NULL) + return NULL; + + /* Make sure we've got enough free fence regs. It's pretty hard to run + * out, luckily, with 8 even on older hardware and us only tiling + * front/back/depth buffers. + */ + if (pI830->next_fence + fence_divide > + (IS_I965G(pI830) ? FENCE_NEW_NR : FENCE_NR)) + { + i830_free_memory(pScrn, mem); + 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++, + mem->offset + mem->size * i / fence_divide, pitch, + mem->size / fence_divide, tile_format); + } + + mem->size = size; + + return mem; +} + +static void +i830_describe_tiling(ScrnInfoPtr pScrn, int verbosity, const char *prefix, + i830_memory *mem, unsigned int tiling_mode) +{ + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%s%s is %stiled\n", prefix, mem->name, + (tiling_mode == FENCE_LINEAR) ? "not " : ""); } -unsigned long -I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool, - long size, unsigned long alignment, int flags) +void +i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix) { I830Ptr pI830 = I830PTR(pScrn); - Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + i830_memory *mem; - if (!result) - return 0; + if (pI830->memory_list == NULL) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sMemory allocator not initialized\n", prefix); + return; + } - /* Make sure these are initialised. */ - result->Size = 0; - result->Key = -1; + if (pI830->memory_list->next->next == NULL) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sNo memory allocations\n", prefix); + return; + } - if (!size) { - return 0; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sMemory allocation layout:\n", prefix); + + for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) { + + if (mem->offset >= pI830->stolen_size && + mem->prev->offset <= pI830->stolen_size) + { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%s0x%08lx: end of stolen memory\n", + prefix, pI830->stolen_size); + } + + if (mem->bus_addr == 0) { + 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, + "%s0x%08lx-0x%08lx: %s (%ld kB, %08lx physical)\n", + prefix, + mem->offset, mem->end - 1, mem->name, + mem->size / 1024, mem->bus_addr); + } } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%s0x%08lx: end of aperture\n", + prefix, pI830->FbMapSize); - switch (flags & FROM_MASK) { - case FROM_POOL_ONLY: - return AllocFromPool(pScrn, result, pool, size, alignment, flags); - case FROM_NEW_ONLY: - if (!dryrun && (pI830->StolenOnly || (pI830->FreeMemory <= 0))) - return 0; - return AllocFromAGP(pScrn, result, size, alignment, flags); - case FROM_ANYWHERE: - if ((!(flags & ALLOCATE_AT_BOTTOM) && (pI830->FreeMemory >= size)) || - (flags & NEED_PHYSICAL_ADDR)) - return AllocFromAGP(pScrn, result, size, alignment, flags); - else - return AllocFromPool(pScrn, result, pool, size, alignment, flags); - default: - /* Shouldn't happen. */ - return 0; + if (pI830->front_buffer != NULL) { + i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer, + pI830->front_tiled); + } + if (pI830->back_buffer != NULL) { + i830_describe_tiling(pScrn, verbosity, prefix, pI830->back_buffer, + pI830->back_tiled); + } + if (pI830->depth_buffer != NULL) { + i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer, + pI830->depth_tiled); } } static Bool -AllocateRingBuffer(ScrnInfoPtr pScrn, int flags) +i830_allocate_ringbuffer(ScrnInfoPtr pScrn, int flags) { I830Ptr pI830 = I830PTR(pScrn); - unsigned long size, alloced; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - - /* Clear ring buffer info */ - memset(pI830->LpRing, 0, sizeof(I830RingBuffer)); - pI830->LpRing->mem.Key = -1; - if (pI830->noAccel) + if (pI830->noAccel || pI830->LpRing->mem != NULL) return TRUE; - /* Ring buffer */ - size = PRIMARY_RINGBUFFER_SIZE; - if (flags & FORCE_LOW) - flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM; - else - flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP; - - alloced = I830AllocVidMem(pScrn, &(pI830->LpRing->mem), - &(pI830->StolenPool), size, - GTT_PAGE_SIZE, flags); - if (alloced < size) { + pI830->LpRing->mem = i830_allocate_memory(pScrn, "ring buffer", + PRIMARY_RINGBUFFER_SIZE, + GTT_PAGE_SIZE, 0); + if (pI830->LpRing->mem == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate Ring Buffer space\n"); } return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the ring buffer at 0x%lx\n", s, - alloced / 1024, pI830->LpRing->mem.Start); - pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1; + + pI830->LpRing->tail_mask = pI830->LpRing->mem->size - 1; return TRUE; } #ifdef I830_XV -/* - * Note, the FORCE_LOW flag is currently not used or supported. +/** + * Allocate space for overlay registers and XAA linear allocator (if + * requested) */ static Bool -AllocateOverlay(ScrnInfoPtr pScrn, int flags) +i830_allocate_overlay(ScrnInfoPtr pScrn, int flags) { I830Ptr pI830 = I830PTR(pScrn); - unsigned long size, alloced; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - - /* Clear overlay info */ - memset(pI830->OverlayMem, 0, sizeof(I830MemRange)); - pI830->OverlayMem->Key = -1; - if (!pI830->XvEnabled) + /* Only allocate if overlay is going to be enabled. */ + if (!pI830->XvEnabled || IS_I965G(pI830)) return TRUE; - /* - * The overlay register space needs a physical address in - * system memory. We get this from the agpgart module using - * a special memory type. - */ - - size = OVERLAY_SIZE; - if (flags & FORCE_LOW) - flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM | NEED_PHYSICAL_ADDR; - else - flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP | NEED_PHYSICAL_ADDR; - - alloced = I830AllocVidMem(pScrn, pI830->OverlayMem, - &(pI830->StolenPool), size, GTT_PAGE_SIZE, - flags); - - /* - * XXX For testing only. Don't enable this unless you know how to set - * physBase. - */ - if (flags & FORCE_LOW) { - ErrorF("AllocateOverlay() doesn't support setting FORCE_LOW\n"); - return FALSE; - } - - if (!dryrun && (alloced < size)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate Overlay register space.\n"); - /* This failure isn't fatal. */ - } else { - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for Overlay registers at 0x%lx " - "(0x%08lx).\n", s, - alloced / 1024, pI830->OverlayMem->Start, - pI830->OverlayMem->Physical); + if (!IS_I965G(pI830)) { + pI830->overlay_regs = i830_allocate_memory(pScrn, "overlay registers", + OVERLAY_SIZE, GTT_PAGE_SIZE, + NEED_PHYSICAL_ADDR); + if (pI830->overlay_regs == NULL) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate Overlay register space.\n"); + /* This failure isn't fatal. */ + } + } } - /* Clear linearmem info */ - if (pI830->LinearAlloc) { - memset(&(pI830->LinearMem), 0, sizeof(I830MemRange)); - pI830->LinearMem.Key = -1; - - size = KB(pI830->LinearAlloc); - alloced = I830AllocVidMem(pScrn, &(pI830->LinearMem), - &(pI830->StolenPool), - size, GTT_PAGE_SIZE, - FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { + if (!pI830->useEXA && pI830->LinearAlloc) { + pI830->xaa_linear = i830_allocate_memory(pScrn, "XAA linear memory", + KB(pI830->LinearAlloc), + GTT_PAGE_SIZE, 0); + if (pI830->xaa_linear == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate linear buffer space\n"); } - } else - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the linear buffer at " - "0x%lx\n", s, - alloced / 1024, pI830->LinearMem.Start); + } } return TRUE; @@ -479,22 +682,6 @@ IsTileable(ScrnInfoPtr pScrn, int pitch) } } -static unsigned long -GetFreeSpace(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned long extra = 0; - - /* First check for free space in StolenPool. */ - if (pI830->StolenPool.Free.Size > 0) - extra = pI830->StolenPool.Free.Size; - /* Next check for unallocated space. */ - if (pI830->FreeMemory > 0) - extra += pI830->FreeMemory; - - return extra; -} - /* This is the 2D rendering vertical coordinate limit. We can ignore * the 3D rendering limits in our 2d pixmap cache allocation, because XAA * doesn't do any 3D rendering to/from the cache lines when using an offset @@ -512,24 +699,23 @@ GetFreeSpace(ScrnInfoPtr pScrn) * \param pI830 I830Ptr for the screen being allocated. * \param FbMemBox */ -static Bool -I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, - I830MemRange *FrontBuffer, I830MemPool *StolenPool, - Bool secondary, const int flags) +static i830_memory * +i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, + Bool secondary, int flags) { Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - unsigned long minspace, avail, lineSize; + unsigned int pitch = pScrn->displayWidth * pI830->cpp; + unsigned long minspace, avail; int cacheLines, maxCacheLines; int verbosity = dryrun ? 4 : 1; const char *s = dryrun ? "[dryrun] " : ""; - Bool tileable; - int align, alignflags; - long size, alloced, fb_height; + int align; + long size, fb_height; + char *name; + i830_memory *front_buffer = NULL; /* Clear everything first. */ memset(FbMemBox, 0, sizeof(*FbMemBox)); - memset(FrontBuffer, 0, sizeof(*FrontBuffer)); - FrontBuffer->Key = -1; /* We'll allocate the fb such that the root window will fit regardless of * rotation. @@ -549,18 +735,16 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, * enough for the virtual screen size, plus some pixmap cache * space if we're using XAA. */ - - lineSize = pScrn->displayWidth * pI830->cpp; - minspace = lineSize * pScrn->virtualY; + minspace = pitch * pScrn->virtualY; avail = pScrn->videoRam * 1024; if (!pI830->useEXA) { - maxCacheLines = (avail - minspace) / lineSize; + maxCacheLines = (avail - minspace) / pitch; /* This shouldn't happen. */ if (maxCacheLines < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal Error: " - "maxCacheLines < 0 in I830Allocate2DMemory()\n"); + "maxCacheLines < 0 in i830_allocate_2d_memory()\n"); maxCacheLines = 0; } if (maxCacheLines > (MAX_2D_HEIGHT - pScrn->virtualY)) @@ -571,11 +755,11 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, } else { int size; - size = 3 * lineSize * pScrn->virtualY; + size = 3 * pitch * pScrn->virtualY; size += 1920 * 1088 * 2 * 2; size = ROUND_TO_PAGE(size); - cacheLines = (size + lineSize - 1) / lineSize; + cacheLines = (size + pitch - 1) / pitch; } if (cacheLines > maxCacheLines) cacheLines = maxCacheLines; @@ -592,125 +776,96 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, cacheLines = 0; } - tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); - if (tileable) { + size = pitch * (fb_height + cacheLines); + size = ROUND_TO_PAGE(size); + + name = secondary ? "secondary front buffer" : "front buffer"; + + /* Attempt to allocate it tiled first if we have page flipping on. */ + if (!flags & ALLOC_NO_TILING && pI830->allowPageFlip && + IsTileable(pScrn, pitch)) + { + /* XXX: probably not the case on 965 */ if (IS_I9XX(pI830)) align = MB(1); else align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; + front_buffer = i830_allocate_memory_tiled(pScrn, name, size, + pitch, align, + flags, TILING_XMAJOR); + pI830->front_tiled = FENCE_XMAJOR; } - size = lineSize * (fb_height + cacheLines); - size = ROUND_TO_PAGE(size); - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sInitial %sframebuffer allocation size: %ld kByte\n", - s, secondary ? "secondary " : "", - size / 1024); - alloced = I830AllocVidMem(pScrn, FrontBuffer, - StolenPool, size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { + /* If not, attempt it linear */ + if (front_buffer == NULL) { + front_buffer = i830_allocate_memory(pScrn, name, size, KB(64), flags); + pI830->front_tiled = FENCE_LINEAR; + } + + if (front_buffer == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " "%sframebuffer. Is your VideoRAM set too low?\n", secondary ? "secondary " : ""); } - return FALSE; + return NULL; } - return TRUE; + return front_buffer; } static Bool -I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags) +i830_allocate_cursor_buffers(xf86CrtcPtr crtc, int flags) { ScrnInfoPtr pScrn = crtc->scrn; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; I830Ptr pI830 = I830PTR(pScrn); Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - long size, alloced; - int cursFlags = 0; - - /* Clear cursor info */ - memset(&intel_crtc->cursor_mem, 0, sizeof(I830MemRange)); - intel_crtc->cursor_mem.Key = -1; - memset(&intel_crtc->cursor_mem_argb, 0, sizeof(I830MemRange)); - intel_crtc->cursor_mem_argb.Key = -1; + long size; if (pI830->SWCursor) return FALSE; - /* - * Mouse cursor -- The i810-i830 need a physical address in system + /* Mouse cursor -- The i810-i830 need a physical address in system * memory from which to upload the cursor. We get this from * the agpgart module using a special memory type. */ size = HWCURSOR_SIZE; - cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP; if (pI830->CursorNeedsPhysical) - cursFlags |= NEED_PHYSICAL_ADDR; + flags |= NEED_PHYSICAL_ADDR; - alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem, - &pI830->StolenPool, size, - GTT_PAGE_SIZE, flags | cursFlags); - if (alloced < size || - (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem.Physical)) - { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate HW cursor space.\n"); + if (intel_crtc->cursor_mem == NULL) { + intel_crtc->cursor_mem = i830_allocate_memory(pScrn, "HW cursor", + size, GTT_PAGE_SIZE, + flags); + if (intel_crtc->cursor_mem == NULL) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate HW cursor space.\n"); + } return FALSE; } - } else { - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for HW cursor at 0x%lx", s, - alloced / 1024, intel_crtc->cursor_mem.Start); - if (pI830->CursorNeedsPhysical) { - xf86ErrorFVerb(verbosity, " (0x%08lx)", - intel_crtc->cursor_mem.Physical); - } - xf86ErrorFVerb(verbosity, "\n"); } - /* Allocate the ARGB cursor space. Its success is optional -- we won't set - * SWCursor if it fails. - */ - size = HWCURSOR_SIZE_ARGB; - cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP; - if (pI830->CursorNeedsPhysical) - cursFlags |= NEED_PHYSICAL_ADDR; - - alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem_argb, - &pI830->StolenPool, size, - GTT_PAGE_SIZE, flags | cursFlags); - if (alloced < size || - (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem_argb.Physical)) - { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate HW (ARGB) cursor space.\n"); - } - } else { - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s, - alloced / 1024, intel_crtc->cursor_mem_argb.Start); - if (pI830->CursorNeedsPhysical) { - xf86ErrorFVerb(verbosity, " (0x%08lx)", - intel_crtc->cursor_mem_argb.Physical); + if (intel_crtc->cursor_mem_argb == NULL) { + /* Allocate the ARGB cursor space. Its success is optional -- we won't + * set SWCursor if it fails. + */ + intel_crtc->cursor_mem_argb = i830_allocate_memory(pScrn, + "HW ARGB cursor", + HWCURSOR_SIZE_ARGB, + GTT_PAGE_SIZE, + flags); + if (intel_crtc->cursor_mem_argb == NULL) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate HW (ARGB) cursor space.\n"); + } } - xf86ErrorFVerb(verbosity, "\n"); } - return FALSE; + return TRUE; } /* @@ -718,18 +873,16 @@ I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags) * ring buffer, scratch memory, HW cursor. */ Bool -I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) +i830_allocate_2d_memory(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - long size, alloced; + unsigned int pitch = pScrn->displayWidth * pI830->cpp; + long size; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - Bool tileable; - int align, alignflags, i; + int i; - DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n", + DPRINTF(PFX, "i830_allocate_2d_memory: inital is %s\n", BOOLTOSTRING(flags & ALLOC_INITIAL)); if (!pI830->StolenOnly && @@ -738,88 +891,70 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "AGP GART support is either not available or cannot " "be used.\n" - "\tMake sure your kernel has agpgart support or has " - "the\n" - "\tagpgart module loaded.\n"); + "\tMake sure your kernel has agpgart support or has\n" + "\tthe agpgart module loaded.\n"); } return FALSE; } + /* Allocate the ring buffer first, so it ends up in stolen mem. */ + i830_allocate_ringbuffer(pScrn, flags); - /* - * The I830 is slightly different from the I830/I815, it has no - * dcache and it has stolen memory by default in its gtt. All - * additional memory must go after it. - */ - - DPRINTF(PFX, - "size == %luk (%lu bytes == pScrn->videoRam)\n" - "pI830->StolenSize == %luk (%lu bytes)\n", - pScrn->videoRam, pScrn->videoRam * 1024, - pI830->StolenPool.Free.Size / 1024, - pI830->StolenPool.Free.Size); - - if (flags & ALLOC_INITIAL) { - if (pI830->NeedRingBufferLow) - AllocateRingBuffer(pScrn, flags | FORCE_LOW); - - /* Unfortunately this doesn't run on the DRY_RUN pass because our - * second head hasn't been created yet..... */ - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { - I830EntPtr pI830Ent = pI830->entityPrivate; - I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); - - if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302, - &pI830->FbMemBox2, - &pI830->FrontBuffer2, - &pI830->StolenPool, - TRUE, flags)) - { - return FALSE; - } - } - if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox, - &pI830->FrontBuffer, &pI830->StolenPool, - FALSE, flags)) - { - return FALSE; + /* Next, allocate other fixed-size allocations we have. */ + if (!pI830->SWCursor) { + /* Allocate cursor memory */ + for (i = 0; i < xf86_config->num_crtc; i++) { + if (!i830_allocate_cursor_buffers(xf86_config->crtc[i], flags) && + !pI830->SWCursor) + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling HW cursor because the cursor memory " + "allocation failed.\n"); + pI830->SWCursor = TRUE; + break; + } } + } + +#ifdef I830_XV + /* Allocate overlay register space and optional XAA linear allocator + * space. The second head in zaphod mode will share the space. + */ + if (I830IsPrimary(pScrn)) + i830_allocate_overlay(pScrn, flags); +#endif #ifdef I830_USE_EXA - if (pI830->useEXA) { + if (pI830->useEXA) { + if (pI830->exa_offscreen == NULL) { /* Default EXA to having 3 screens worth of offscreen memory space * (for pixmaps), plus a double-buffered, 1920x1088 video's worth. + * + * XXX: It would be nice to auto-size it larger if the user + * specified a larger size, or to fit along with texture and FB + * memory if a low videoRam is specified. */ - size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY; + size = 3 * pitch * pScrn->virtualY; size += 1920 * 1088 * 2 * 2; size = ROUND_TO_PAGE(size); - alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), - &(pI830->StolenPool), size, 1, - flags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { + pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen", + size, 1, flags); + if (pI830->exa_offscreen == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " "offscreen memory. Not enough VRAM?\n"); } return FALSE; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Successful allocation of " - "EXA offscreen memory at 0x%lx, size %ld KB\n", - pI830->Offscreen.Start, pI830->Offscreen.Size/1024); } } - if (pI830->useEXA && IS_I965G(pI830)) { - memset(&(pI830->EXAStateMem), 0, sizeof(I830MemRange)); - pI830->EXAStateMem.Key = -1; - size = ROUND_TO_PAGE(EXA_LINEAR_EXTRA); - align = GTT_PAGE_SIZE; - alloced = I830AllocVidMem(pScrn, &(pI830->EXAStateMem), - &(pI830->StolenPool), size, align, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { + + if (IS_I965G(pI830) && pI830->exa_965_state == NULL) { + pI830->exa_965_state = + i830_allocate_memory(pScrn, "exa G965 state buffer", + EXA_LINEAR_EXTRA, GTT_PAGE_SIZE, + flags); + if (pI830->exa_965_state == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "G965: Failed to allocate exa state buffer " @@ -827,228 +962,85 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) } return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the G965 exa state buffer " - "at 0x%lx - 0x%lx.\n", s, - alloced / 1024, pI830->EXAStateMem.Start, - pI830->EXAStateMem.End); - } -#endif - } else { - long lineSize; - long extra = 0; - long maxFb = 0; - - /* - * XXX Need to "free" up any 3D allocations if the DRI ended up - * and make them available for 2D. The best way to do this would - * be position all of those regions contiguously at the end of the - * StolenPool. - */ - extra = GetFreeSpace(pScrn); - - if (extra == 0) - return TRUE; - - maxFb = pI830->FrontBuffer.Size + extra; - lineSize = pScrn->displayWidth * pI830->cpp; - maxFb = ROUND_DOWN_TO(maxFb, lineSize); - if (maxFb > lineSize * MAX_2D_HEIGHT) - maxFb = lineSize * MAX_2D_HEIGHT; - if (0/*maxFb > pI830->FrontBuffer.Size*/) { - unsigned long oldsize; - /* - * Sanity check -- the fb should be the last thing allocated at - * the bottom of the stolen pool. - */ - if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Internal error in I830Allocate2DMemory():\n\t" - "Framebuffer isn't the last allocation at the " - "bottom of StolenPool\n\t(%lx != %lx).\n", - pI830->FrontBuffer.End, - pI830->StolenPool.Free.Start); - return FALSE; - } - /* - * XXX Maybe should have a "Free" function. This should be - * the only place where a region is resized, and we know that - * the fb is always at the bottom of the aperture/stolen pool, - * and is the only region that is allocated bottom-up. - * Allowing for more general realloction would require a smarter - * allocation system. - */ - oldsize = pI830->FrontBuffer.Size; - pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size; - pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size; - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sUpdated framebuffer allocation size from %ld " - "to %ld kByte\n", s, oldsize / 1024, maxFb / 1024); - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sUpdated pixmap cache from %ld scanlines to %ld " - "scanlines\n", s, - oldsize / lineSize - pScrn->virtualY, - maxFb / lineSize - pScrn->virtualY); - pI830->FbMemBox.y2 = maxFb / lineSize; - tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), - &(pI830->StolenPool), maxFb, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < maxFb) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to re-allocate framebuffer\n"); - } - return FALSE; - } } - return TRUE; } +#endif /* I830_USE_EXA */ -#if REMAP_RESERVED - /* - * Allocate a dummy page to pass when attempting to rebind the - * pre-allocated region. - */ - if (!dryrun) { - memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy)); - pI830->Dummy.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, - NULL); - pI830->Dummy.Offset = 0; - } -#endif + if (flags & ALLOC_INITIAL) { - if (!pI830->SWCursor && !dryrun) { - for (i = 0; i < xf86_config->num_crtc; i++) { - if (!I830AllocateCursorBuffers(xf86_config->crtc[i], flags) && - pI830->SWCursor) - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling HW cursor because the cursor memory " - "allocation failed.\n"); - pI830->SWCursor = TRUE; - break; - } + /* Unfortunately this doesn't run on the DRY_RUN pass because our + * second head hasn't been created yet..... */ + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { + I830EntPtr pI830Ent = pI830->entityPrivate; + I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); + + pI830->front_buffer_2 = + i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302, + &pI830->FbMemBox2, + TRUE, flags); + if (pI830->front_buffer_2 == NULL) + return FALSE; } + pI830->front_buffer = + i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, + FALSE, flags); + if (pI830->front_buffer == NULL) + return FALSE; } -#ifdef I830_XV - AllocateOverlay(pScrn, flags); -#endif - - if (!pI830->NeedRingBufferLow) - AllocateRingBuffer(pScrn, flags); - - /* Clear scratch info */ - memset(&(pI830->Scratch), 0, sizeof(I830MemRange)); - pI830->Scratch.Key = -1; - memset(&(pI830->Scratch2), 0, sizeof(I830MemRange)); - pI830->Scratch2.Key = -1; - - if (!pI830->noAccel) { - size = MAX_SCRATCH_BUFFER_SIZE; - alloced = I830AllocVidMem(pScrn, &(pI830->Scratch), - &(pI830->StolenPool), - size, GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { - size = MIN_SCRATCH_BUFFER_SIZE; - alloced = I830AllocVidMem(pScrn, &(pI830->Scratch), - &(pI830->StolenPool), size, - GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - } - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate scratch buffer space\n"); + if (!pI830->noAccel && !pI830->useEXA) { + if (pI830->xaa_scratch == NULL) { + pI830->xaa_scratch = + i830_allocate_memory(pScrn, "xaa scratch", + MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE, + flags); + if (pI830->xaa_scratch == NULL) { + pI830->xaa_scratch = + i830_allocate_memory(pScrn, "xaa scratch", + MIN_SCRATCH_BUFFER_SIZE, + GTT_PAGE_SIZE, + flags); + if (pI830->xaa_scratch == NULL) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate scratch buffer " + "space\n"); + } + return FALSE; + } } - return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the scratch buffer at 0x%lx\n", - s, alloced / 1024, pI830->Scratch.Start); /* Let's allocate another scratch buffer for the second head */ /* Again, this code won't execute on the dry run pass */ - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { - size = MAX_SCRATCH_BUFFER_SIZE; - alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2), - &(pI830->StolenPool), - size, GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { - size = MIN_SCRATCH_BUFFER_SIZE; - alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2), - &(pI830->StolenPool), size, - GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | - ALLOCATE_AT_TOP); - } - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate second scratch buffer " - "space\n"); + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 && + pI830->xaa_scratch_2 == NULL) + { + pI830->xaa_scratch_2 = + i830_allocate_memory(pScrn, "xaa scratch 2", + MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE, + flags); + if (pI830->xaa_scratch_2 == NULL) { + pI830->xaa_scratch_2 = + i830_allocate_memory(pScrn, "xaa scratch 2", + MIN_SCRATCH_BUFFER_SIZE, + GTT_PAGE_SIZE, + flags); + if (pI830->xaa_scratch_2 == NULL) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate secondary scratch " + "buffer space\n"); + } + return FALSE; } - return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the second scratch buffer " - "at 0x%lx\n", s, - alloced / 1024, pI830->Scratch2.Start); } } return TRUE; } -void -I830ResetAllocations(ScrnInfoPtr pScrn, const int flags) -{ - I830Ptr pI830 = I830PTR(pScrn); - - pI830->MemoryAperture.Start = pI830->StolenMemory.End; - pI830->MemoryAperture.End = pI830->FbMapSize; - pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size; -#ifdef XF86DRI - if (!pI830->directRenderingDisabled) { - pI830->MemoryAperture.End -= KB(pI830->mmSize); - pI830->MemoryAperture.Size -= KB(pI830->mmSize); - } -#endif - pI830->StolenPool.Fixed = pI830->StolenMemory; - pI830->StolenPool.Total = pI830->StolenMemory; - pI830->StolenPool.Free = pI830->StolenPool.Total; - pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size; - pI830->allocatedMemory = 0; -} - -long -I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - long allocated; - - allocated = pI830->StolenPool.Total.Size + pI830->allocatedMemory; - if (allocated > pI830->TotalVideoRam) - return allocated - pI830->TotalVideoRam; - else - return 0; -} - #ifdef XF86DRI static unsigned int myLog2(unsigned int n) @@ -1062,16 +1054,13 @@ myLog2(unsigned int n) return log2; } -Bool -I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags) +static Bool +i830_allocate_backbuffer(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); - unsigned long size, alloced, align = 0; - Bool tileable; + unsigned int pitch = pScrn->displayWidth * pI830->cpp; + unsigned long size; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - int lines; int height; if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) @@ -1079,152 +1068,106 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags) else height = pScrn->virtualX; - /* Back Buffer */ - memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer)); - pI830->BackBuffer.Key = -1; - tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); - if (tileable) { - /* Make the height a multiple of the tile height (16) */ - lines = (height + 15) / 16 * 16; - } else { - lines = height; + /* Try to allocate on the best tile-friendly boundaries. */ + if (!(flags & ALLOC_NO_TILING) && IsTileable(pScrn, pitch)) + { + size = ROUND_TO_PAGE(pitch * ALIGN(height, 16)); + pI830->back_buffer = + i830_allocate_memory_tiled(pScrn, "back buffer", + size, pitch, GTT_PAGE_SIZE, + flags | ALIGN_BOTH_ENDS, + TILING_XMAJOR); + pI830->back_tiled = FENCE_XMAJOR; } - size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp); - /* - * Try to allocate on the best tile-friendly boundaries. - */ - alloced = 0; - if (tileable) { - align = GetBestTileAlignment(size); - for (align = GetBestTileAlignment(size); - align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) - { - alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer), - &(pI830->StolenPool), size, align, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | - ALIGN_BOTH_ENDS); - if (alloced >= size) - break; - } + /* Otherwise, just allocate it linear */ + if (pI830->back_buffer == NULL) { + size = ROUND_TO_PAGE(pitch * height); + pI830->back_buffer = i830_allocate_memory(pScrn, "back buffer", + size, GTT_PAGE_SIZE, + flags | ALIGN_BOTH_ENDS); + pI830->back_tiled = FENCE_LINEAR; } - if (alloced < size) { - /* Give up on trying to tile */ - tileable = FALSE; - size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp); - align = GTT_PAGE_SIZE; - alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer), - &(pI830->StolenPool), size, align, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - } - if (alloced < size) { + + if (pI830->back_buffer == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate back buffer space.\n"); } return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s, - alloced / 1024, pI830->BackBuffer.Start); return TRUE; } -Bool -I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags) +static Bool +i830_allocate_depthbuffer(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); - unsigned long size, alloced, align = 0; - Bool tileable; + unsigned long size; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - int lines; + unsigned int pitch = pScrn->displayWidth * pI830->cpp; int height; + /* XXX: this rotation stuff is bogus */ if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) height = pScrn->virtualY; else height = pScrn->virtualX; - /* Depth Buffer -- same size as the back buffer */ - memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer)); - pI830->DepthBuffer.Key = -1; - tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); - if (tileable) { - /* Make the height a multiple of the tile height (16) */ - lines = (height + 15) / 16 * 16; - } else { - lines = height; - } + /* First try allocating it tiled */ + if (!(flags & ALLOC_NO_TILING) && IsTileable(pScrn, pitch)) + { + size = ROUND_TO_PAGE(pitch * ALIGN(height, 16)); - size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp); - /* - * Try to allocate on the best tile-friendly boundaries. - */ - alloced = 0; - if (tileable) { - align = GetBestTileAlignment(size); - for (align = GetBestTileAlignment(size); - align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) - { - alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer), - &(pI830->StolenPool), size, align, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | - ALIGN_BOTH_ENDS); - if (alloced >= size) - break; - } + pI830->depth_buffer = + i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch, + GTT_PAGE_SIZE, flags | ALIGN_BOTH_ENDS, + TILING_YMAJOR); + pI830->depth_tiled = FENCE_YMAJOR; } - if (alloced < size) { - /* Give up on trying to tile */ - tileable = FALSE; - size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp); - align = GTT_PAGE_SIZE; - alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer), - &(pI830->StolenPool), size, align, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); + + /* Otherwise, allocate it linear. */ + if (pI830->depth_buffer == NULL) { + size = ROUND_TO_PAGE(pitch * height); + pI830->depth_buffer = + i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE, + flags); + pI830->depth_tiled = FENCE_LINEAR; } - if (alloced < size) { + + if (pI830->depth_buffer == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate depth buffer space.\n"); } return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s, - alloced / 1024, pI830->DepthBuffer.Start); return TRUE; } -Bool -I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags) +static Bool +i830_allocate_texture_memory(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); - unsigned long size, alloced; + unsigned long size; int i; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - /* Allocate the remaining space for textures. */ - memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem)); - pI830->TexMem.Key = -1; + if (pI830->mmModeFlags & I830_KERNEL_MM) { + pI830->memory_manager = + i830_allocate_aperture(pScrn, "DRI memory manager", + pI830->mmSize, GTT_PAGE_SIZE, + flags | ALIGN_BOTH_ENDS); + /* XXX: try memory manager size backoff here? */ + if (pI830->memory_manager == NULL) + return FALSE; + } if (pI830->mmModeFlags & I830_KERNEL_TEX) { - if (dryrun && pI830->pEnt->device->videoRam == 0) { - /* If we're laying out a default-sized allocation, then don't be - * too greedy and just ask for 32MB. - */ - size = MB(32); - } else { - size = GetFreeSpace(pScrn); - } + /* XXX: auto-sizing */ + size = MB(32); if (dryrun && (size < MB(1))) size = MB(1); i = myLog2(size / I830_NR_TEX_REGIONS); @@ -1237,306 +1180,157 @@ I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags) if (size < KB(512)) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Less than 512 kBytes for texture space (real %ld " + "Less than 512 kBytes for texture space (real %ld" "kBytes).\n", size / 1024); } return FALSE; } - alloced = I830AllocVidMem(pScrn, &(pI830->TexMem), - &(pI830->StolenPool), size, GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { + pI830->textures = i830_allocate_memory(pScrn, "textures", size, + GTT_PAGE_SIZE, flags); + if (pI830->textures == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate texture space.\n"); } return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for textures at 0x%lx\n", s, - alloced / 1024, pI830->TexMem.Start); } return TRUE; } Bool -I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) +i830_allocate_3d_memory(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); - unsigned long size, alloced; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; DPRINTF(PFX, "I830Allocate3DMemory\n"); /* Space for logical context. 32k is fine for right now. */ - memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem)); - pI830->ContextMem.Key = -1; - size = KB(32); - alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem), - &(pI830->StolenPool), size, GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { + pI830->logical_context = i830_allocate_memory(pScrn, "logical 3D context", + KB(32), GTT_PAGE_SIZE, + flags); + if (pI830->logical_context == NULL) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate logical context space.\n"); } return FALSE; } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for the logical context at 0x%lx.\n", s, - alloced / 1024, pI830->ContextMem.Start); - if (!I830AllocateBackBuffer(pScrn, flags)) + if (!i830_allocate_backbuffer(pScrn, flags)) return FALSE; - if (!I830AllocateDepthBuffer(pScrn, flags)) + if (!i830_allocate_depthbuffer(pScrn, flags)) return FALSE; - if (!I830AllocateTextureMemory(pScrn, flags)) + if (!i830_allocate_texture_memory(pScrn, flags)) return FALSE; return TRUE; } #endif -/* Allocate pool space that isn't pre-allocated */ -Bool -I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool) -{ - I830Ptr pI830 = I830PTR(pScrn); - - DPRINTF(PFX, "I830DoPoolAllocation\n"); - - if (!pool) - return FALSE; - - /* - * Sanity check: there shouldn't be an allocation required when - * there is only stolen memory. - */ - if (pI830->StolenOnly && (pool->Total.Size > pool->Fixed.Size)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "I830DoPoolAllocation(): pool size is greater than the " - "preallocated size,\n\t" - "and there is no allocatable memory.\n"); - return FALSE; - } - - if (pool->Total.Size > pool->Fixed.Size) { - pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size; - pool->Allocated.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, - pool->Allocated.Size, 0, - NULL); - if (pool->Allocated.Key == -1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n"); - return FALSE; - } - pool->Allocated.Start = pool->Fixed.End; - pool->Allocated.End = pool->Total.Size; - pool->Allocated.Offset = pool->Allocated.Start; - } else - pool->Allocated.Key = -1; - return TRUE; -} - -static unsigned long topOfMem = 0; - -/* - * These modify the way memory is positioned within the aperture. - * - * By default, memory allocated from the bottom or specifically within - * the pool at the bottom gets allocated from the "stolen pool", which is - * actually the stolen memory plus any extra allocated to make it a larger - * contiguous region. Memory allocated from the AGP is allocated top-down - * from the end of the aperture space. Memory allocated "from top" defaults - * to AGP if there is enough "free space". The total allocation (stolen + - * extra) doesn't exceed the orignal pScrn->videoRam amount (this isn't true - * when memory allocated from AGP gets moved into the pool by one of the - * following options. - * - * XXX Write a better description. - * - */ -#define PACK_RANGES 0 -#define POOL_RANGES 0 - -Bool -I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem) -{ -#if POOL_RANGES - I830Ptr pI830 = I830PTR(pScrn); -#endif - - if (!mem) - return FALSE; - - if (mem->Pool && mem->Key == -1 && mem->Start < 0) { - mem->Start = mem->Pool->Total.End + mem->Start; - mem->End = mem->Start + mem->Size; - } -#if PACK_RANGES - /* - * Map AGP-allocated areas at the top of the stolen area, resulting in - * a contiguous region in the aperture. Normally most AGP-allocated areas - * will be at the top of the aperture, making alignment requirements - * easier to achieve. This optin is primarily for debugging purposes, - * and using this option can break any special alignment requirements. - */ - if (!mem->Pool && mem->Start != 0 && mem->Key != -1 && - mem->Physical == 0 && mem->Offset != 0) - { - long diff; - if (mem->Offset != mem->Start) - ErrorF("mem %p, Offset != Start\n", mem); - diff = mem->Offset - topOfMem; - mem->Start -= diff; - mem->End -= diff; - mem->Offset -= diff; - topOfMem += mem->Size; - } -#elif POOL_RANGES - /* - * Move AGP-allocated regions (that don't need a physical address) into - * the pre-allocated pool when there's enough space to do so. Note: the - * AGP-allocated areas aren't freed. This option is primarily for - * debugging purposes, and using it can break any special alignment - * requirements. - */ - if (!mem->Pool && mem->Start >= pI830->StolenPool.Free.End && - mem->Key != -1 && mem->Physical == 0 && mem->Offset != 0 && - pI830->StolenPool.Free.Size >= mem->Size) - { - long diff; - - if (mem->Offset != mem->Start) - ErrorF("mem %p, Offset != Start\n", mem); - diff = mem->Offset - pI830->StolenPool.Free.Start; - mem->Start -= diff; - mem->End -= diff; - mem->Offset -= diff; - mem->Key = -1; - pI830->StolenPool.Free.Start += mem->Size; - pI830->StolenPool.Free.Size -= mem->Size; - } -#endif - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "%p: Memory at offset 0x%08lx, size %ld kBytes\n", (void *)mem, - mem->Start, mem->Size / 1024); - return TRUE; -} - -Bool -I830FixupOffsets(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; - - DPRINTF(PFX, "I830FixupOffsets\n"); - - topOfMem = pI830->StolenPool.Total.End; - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - I830FixOffset(pScrn, &(pI830->FrontBuffer2)); - I830FixOffset(pScrn, &(pI830->FrontBuffer)); - - for (i = 0; i < xf86_config->num_crtc; i++) { - I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; - - I830FixOffset(pScrn, &intel_crtc->cursor_mem); - I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb); - } - - I830FixOffset(pScrn, &(pI830->LpRing->mem)); - I830FixOffset(pScrn, &(pI830->Scratch)); - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - I830FixOffset(pScrn, &(pI830->Scratch2)); -#ifdef I830_XV - if (pI830->XvEnabled) { - I830FixOffset(pScrn, pI830->OverlayMem); - if (pI830->LinearAlloc) - I830FixOffset(pScrn, &(pI830->LinearMem)); - } -#endif -#ifdef XF86DRI - if (pI830->directRenderingEnabled) { - I830FixOffset(pScrn, &(pI830->ContextMem)); - I830FixOffset(pScrn, &(pI830->BackBuffer)); - I830FixOffset(pScrn, &(pI830->DepthBuffer)); - if (pI830->mmModeFlags & I830_KERNEL_TEX) { - I830FixOffset(pScrn, &(pI830->TexMem)); - } - } -#endif -#ifdef I830_USE_EXA - if (pI830->useEXA) { - I830FixOffset(pScrn, &(pI830->Offscreen)); - if (IS_I965G(pI830)) - I830FixOffset(pScrn, &(pI830->EXAStateMem)); - } -#endif - return TRUE; -} - #ifdef XF86DRI -/* Tiled memory is good... really, really good... +/** + * Sets up a fence area for the hardware. * - * 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'. + * The fences control automatic tiled address swizzling for CPU access of the + * framebuffer. */ static void -SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, - unsigned int size) +i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset, + unsigned int pitch, unsigned int size, + enum tile_format tile_format) { I830Ptr pI830 = I830PTR(pScrn); - I830RegPtr i830Reg = &pI830->ModeReg; CARD32 val; CARD32 fence_mask = 0; unsigned int fence_pitch; - DPRINTF(PFX, "SetFence: %d, 0x%08x, %d, %d kByte\n", - nr, start, pitch, size / 1024); + DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n", + nr, offset, pitch, size / 1024); + + assert(tile_format != TILING_NONE); - if (nr < 0 || nr > 7) { + if (IS_I965G(pI830)) { + if (nr < 0 || nr >= FENCE_NEW_NR) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "i830_set_fence(): fence %d out of range\n",nr); + return; + } + + switch (tile_format) { + case TILING_XMAJOR: + pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1; + pI830->fence[nr] |= I965_FENCE_X_MAJOR; + break; + case TILING_YMAJOR: + /* YMajor can be 128B aligned but the current code dictates + * otherwise. This isn't a problem apart from memory waste. + * FIXME */ + pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1; + pI830->fence[nr] |= I965_FENCE_Y_MAJOR; + break; + case TILING_NONE: + break; + } + + /* XXX Is it the next page, or the last page of the fenced region? */ + pI830->fence[FENCE_NEW_NR + nr] = offset + size; + return; + } + + if (nr < 0 || nr >= FENCE_NR) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: fence %d out of range\n",nr); + "i830_set_fence(): fence %d out of range\n",nr); return; } - i830Reg->Fence[nr] = 0; + 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) { + if (offset & fence_mask) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: %d: start (0x%08x) is not %s aligned\n", - nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k"); + "i830_set_fence(): %d: offset (0x%08x) is not %s aligned\n", + nr, offset, (IS_I9XX(pI830)) ? "1MB" : "512k"); return; } - if (start % size) { + if (offset % size) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n", - nr, start, size / 1024); + "i830_set_fence(): %d: offset (0x%08x) is not size (%dk) " + "aligned\n", + nr, offset, size / 1024); return; } if (pitch & 127) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n", + "i830_set_fence(): %d: pitch (%d) not a multiple of 128 " + "bytes\n", nr, pitch); return; } - val = (start | FENCE_X_MAJOR | FENCE_VALID); + val = offset | FENCE_VALID; + + switch (tile_format) { + case TILING_XMAJOR: + val |= FENCE_X_MAJOR; + break; + case TILING_YMAJOR: + val |= FENCE_Y_MAJOR; + break; + case TILING_NONE: + break; + } if (IS_I9XX(pI830)) { switch (size) { @@ -1552,9 +1346,9 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, case MB(8): val |= I915G_FENCE_SIZE_8M; break; - case MB(16): - val |= I915G_FENCE_SIZE_16M; - break; + case MB(16): + val |= I915G_FENCE_SIZE_16M; + break; case MB(32): val |= I915G_FENCE_SIZE_32M; break; @@ -1562,8 +1356,8 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, val |= I915G_FENCE_SIZE_64M; break; default: - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: %d: illegal size (%d kByte)\n", + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "i830_set_fence(): %d: illegal size (%d kByte)\n", nr, size / 1024); return; } @@ -1594,8 +1388,8 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, val |= FENCE_SIZE_64M; break; default: - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: %d: illegal size (%d kByte)\n", + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "i830_set_fence(): %d: illegal size (%d kByte)\n", nr, size / 1024); return; } @@ -1620,8 +1414,8 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, val |= FENCE_PITCH_8; break; case 16: - val |= FENCE_PITCH_16; - break; + val |= FENCE_PITCH_16; + break; case 32: val |= FENCE_PITCH_32; break; @@ -1629,352 +1423,82 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, val |= FENCE_PITCH_64; break; default: - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: %d: illegal pitch (%d)\n", nr, pitch); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "i830_set_fence(): %d: illegal pitch (%d)\n", nr, pitch); return; } - i830Reg->Fence[nr] = val; + pI830->fence[nr] = val; } - -static Bool -MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem, unsigned int fence) -{ - I830Ptr pI830 = I830PTR(pScrn); - int pitch, ntiles, i; - -#if 0 - /* Hack to "improve" the alignment of the front buffer. */ - while (!(pMem->Start & ~pMem->Alignment) && pMem->Alignment < 0x00400000 ) - pMem->Alignment <<= 1; #endif - if (tileGeneration != serverGeneration) { - tileGeneration = serverGeneration; - nextTile = 0; - } - - pitch = pScrn->displayWidth * pI830->cpp; - - if (IS_I965G(pI830)) { - I830RegPtr i830Reg = &pI830->ModeReg; - - switch (fence) { - case FENCE_XMAJOR: - i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) | - pMem->Start | 1; - break; - case FENCE_YMAJOR: - /* YMajor can be 128B aligned but the current code dictates - * otherwise. This isn't a problem apart from memory waste. - * FIXME */ - i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) | - pMem->Start | 1; - i830Reg->Fence[nextTile] |= (1<<1); - break; - default: - case FENCE_LINEAR: - break; - } - - i830Reg->Fence[nextTile+FENCE_NEW_NR] = pMem->End; - nextTile++; - return TRUE; - } - - /* - * 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(pScrn, nextTile, pMem->Start + i * pMem->Alignment, - pitch, pMem->Alignment); - } - return TRUE; -} - -void -I830SetupMemoryTiling(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int i; - - /* Clear out */ - if (IS_I965G(pI830)) { - for (i = 0; i < FENCE_NEW_NR*2; i++) - pI830->ModeReg.Fence[i] = 0; - } else { - for (i = 0; i < 8; i++) - pI830->ModeReg.Fence[i] = 0; - } - - nextTile = 0; - tileGeneration = -1; - - /* We currently only attempt to tile the back and depth buffers. */ - if (!pI830->directRenderingEnabled) - return; - - if (!IsTileable(pScrn, pScrn->displayWidth * pI830->cpp)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "I830SetupMemoryTiling: Not tileable 0x%x\n", - pScrn->displayWidth * pI830->cpp); - pI830->allowPageFlip = FALSE; - return; - } - - pI830->front_tiled = FENCE_LINEAR; - pI830->back_tiled = FENCE_LINEAR; - pI830->depth_tiled = FENCE_LINEAR; - - if (pI830->allowPageFlip) { - if (pI830->allowPageFlip && pI830->FrontBuffer.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->FrontBuffer), FENCE_XMAJOR)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Activating tiled memory for the front buffer\n"); - pI830->front_tiled = FENCE_XMAJOR; - } else { - pI830->allowPageFlip = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MakeTiles failed for the front buffer\n"); - } - } else { - pI830->allowPageFlip = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Alignment bad for the front buffer\n"); - } - } - - /* - * We tried to get the best alignment during the allocation. Check - * the alignment values to tell. If well-aligned allocations were - * successful, the address range reserved is a multiple of the align - * value. - */ - if (pI830->BackBuffer.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->BackBuffer), FENCE_XMAJOR)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Activating tiled memory for the back buffer.\n"); - pI830->back_tiled = FENCE_XMAJOR; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MakeTiles failed for the back buffer.\n"); - pI830->allowPageFlip = FALSE; - } - } - - if (pI830->DepthBuffer.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Activating tiled memory for the depth buffer.\n"); - pI830->depth_tiled = FENCE_YMAJOR; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MakeTiles failed for the depth buffer.\n"); - } - } -} -#endif /* XF86DRI */ - -static Bool -BindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem) -{ - if (!mem) - return FALSE; - - if (mem->Key == -1) - return TRUE; - - return xf86BindGARTMemory(pScrn->scrnIndex, mem->Key, mem->Offset); -} - +/** + * Called at EnterVT to grab the AGP GART and bind our allocations. + * + * In zaphod mode, this will walk the list trying to bind twice, since each + * pI830 points to the same allocation list, but the bind_memory will just + * no-op then. + */ Bool -I830BindAGPMemory(ScrnInfoPtr pScrn) +i830_bind_all_memory(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - DPRINTF(PFX, - "I830BindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n", - BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound)); - - if (pI830->StolenOnly == TRUE) + if (pI830->StolenOnly == TRUE || pI830->memory_list == NULL) return TRUE; - if (xf86AgpGARTSupported() && !pI830->GttBound) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; + if (xf86AgpGARTSupported() && !pI830->gtt_acquired) { + i830_memory *mem; if (!xf86AcquireGART(pScrn->scrnIndex)) return FALSE; -#if REMAP_RESERVED - /* Rebind the pre-allocated region. */ - BindMemRange(pScrn, &(pI830->Dummy)); -#endif - - if (!BindMemRange(pScrn, &(pI830->StolenPool.Allocated))) - return FALSE; - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - if (!BindMemRange(pScrn, &(pI830->FrontBuffer2))) - return FALSE; - if (!BindMemRange(pScrn, &(pI830->FrontBuffer))) - return FALSE; + pI830->gtt_acquired = TRUE; - for (i = 0; i < xf86_config->num_crtc; i++) { - I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; - - if (!BindMemRange(pScrn, &intel_crtc->cursor_mem)) - return FALSE; - if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb)) - return FALSE; - } - if (!BindMemRange(pScrn, &(pI830->LpRing->mem))) - return FALSE; - if (!BindMemRange(pScrn, &(pI830->Scratch))) - return FALSE; - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - if (!BindMemRange(pScrn, &(pI830->Scratch2))) - return FALSE; -#ifdef I830_XV - if (pI830->XvEnabled) { - if (!BindMemRange(pScrn, pI830->OverlayMem)) - return FALSE; - if (pI830->LinearAlloc) - if (!BindMemRange(pScrn, &(pI830->LinearMem))) - return FALSE; - } -#endif -#ifdef XF86DRI - if (pI830->directRenderingEnabled) { - if (!BindMemRange(pScrn, &(pI830->ContextMem))) - return FALSE; - if (!BindMemRange(pScrn, &(pI830->BackBuffer))) - return FALSE; - if (!BindMemRange(pScrn, &(pI830->DepthBuffer))) - return FALSE; - if ((pI830->mmModeFlags & I830_KERNEL_TEX) && - !BindMemRange(pScrn, &(pI830->TexMem))) - return FALSE; - } -#endif -#ifdef I830_USE_EXA - if (pI830->useEXA) { - if (!BindMemRange(pScrn, &(pI830->Offscreen))) - return FALSE; - if (IS_I965G(pI830) && !BindMemRange(pScrn, &(pI830->EXAStateMem))) - return FALSE; + for (mem = pI830->memory_list->next; mem->next != NULL; + mem = mem->next) + { + if (!i830_bind_memory(pScrn, mem)) { + /* This shouldn't happen */ + FatalError("Couldn't bind memory for %s\n", mem->name); + } } -#endif - pI830->GttBound = 1; } return TRUE; } -static Bool -UnbindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem) -{ - if (!mem) - return FALSE; - - if (mem->Key == -1) - return TRUE; - - return xf86UnbindGARTMemory(pScrn->scrnIndex, mem->Key); -} - - +/** Called at LeaveVT, to unbind all of our AGP allocations. */ Bool -I830UnbindAGPMemory(ScrnInfoPtr pScrn) +i830_unbind_all_memory(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - DPRINTF(PFX, - "I830UnbindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n", - BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound)); - if (pI830->StolenOnly == TRUE) return TRUE; - if (xf86AgpGARTSupported() && pI830->GttBound) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; + if (xf86AgpGARTSupported() && pI830->gtt_acquired) { + i830_memory *mem; -#if REMAP_RESERVED - /* "unbind" the pre-allocated region. */ - UnbindMemRange(pScrn, &(pI830->Dummy)); -#endif - - if (!UnbindMemRange(pScrn, &(pI830->StolenPool.Allocated))) - return FALSE; - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer2))) - return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer))) - return FALSE; - - for (i = 0; i < xf86_config->num_crtc; i++) { - I830CrtcPrivatePtr intel_crtc = - xf86_config->crtc[i]->driver_private; - - if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem)) - return FALSE; - if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb)) - return FALSE; + for (mem = pI830->memory_list->next; mem->next != NULL; + mem = mem->next) + { + i830_unbind_memory(pScrn, mem); } - if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem))) - return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->Scratch))) - return FALSE; - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) - if (!UnbindMemRange(pScrn, &(pI830->Scratch2))) - return FALSE; -#ifdef I830_XV - if (pI830->XvEnabled) { - if (!UnbindMemRange(pScrn, pI830->OverlayMem)) - return FALSE; - if (pI830->LinearAlloc) - if (!UnbindMemRange(pScrn, &(pI830->LinearMem))) - return FALSE; - } -#endif -#ifdef XF86DRI - if (pI830->directRenderingEnabled) { - if (!UnbindMemRange(pScrn, &(pI830->ContextMem))) - return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->BackBuffer))) - return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer))) - return FALSE; - if ((pI830->mmModeFlags & I830_KERNEL_TEX) && - !UnbindMemRange(pScrn, &(pI830->TexMem))) - return FALSE; - } -#endif -#ifdef I830_USE_EXA - if (pI830->useEXA) { - if (!UnbindMemRange(pScrn, &(pI830->Offscreen))) - return FALSE; - if (IS_I965G(pI830) && !UnbindMemRange(pScrn, - &(pI830->EXAStateMem))) - return FALSE; - } -#endif + pI830->gtt_acquired = FALSE; + if (!xf86ReleaseGART(pScrn->scrnIndex)) return FALSE; - - pI830->GttBound = 0; } return TRUE; } +/** + * Returns the amount of system memory that could potentially be allocated + * from AGP, in kB. + */ long I830CheckAvailableMemory(ScrnInfoPtr pScrn) { diff --git a/src/i830_video.c b/src/i830_video.c index 22f5bee4..92f094fa 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -184,9 +184,9 @@ void exaMoveInPixmap (PixmapPtr pPixmap); OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ } \ if (IS_I965G(pI830)) \ - OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); \ + OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE); \ else \ - OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ + OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ @@ -202,9 +202,9 @@ void exaMoveInPixmap (PixmapPtr pPixmap); OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF); \ if (IS_I965G(pI830)) \ - OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); \ + OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE); \ else \ - OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ + OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ @@ -496,10 +496,10 @@ I830ResetVideo(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset); OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n", - pI830->FbBase, pI830->OverlayMem->Start, overlay); + pI830->FbBase, pI830->overlay_regs->offset, overlay); /* * Default to maximum image size in YV12 */ @@ -926,7 +926,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv = (I830PortPrivPtr) data; I830Ptr pI830 = I830PTR(pScrn); I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset); if (pPriv->textured) { /* XXX: Currently the brightness/saturation attributes aren't hooked up. @@ -1553,7 +1553,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset); unsigned int swidth; unsigned int mask, shift, offsety, offsetu; int tmp; @@ -2076,7 +2076,8 @@ I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, /* Converts an offset from XAA's linear allocator to an offset from the * start of fb. */ -#define XAA_OFFSET_TO_OFFSET(x) (pI830->FrontBuffer.Start + (x * pI830->cpp)) +#define XAA_OFFSET_TO_OFFSET(x) \ + (pI830->front_buffer->offset + (x * pI830->cpp)) /* The XFree86 linear allocator operates in units of screen pixels, * sadly. @@ -2160,7 +2161,7 @@ I830PutImage(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv = (I830PortPrivPtr) data; ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset); PixmapPtr pPixmap; INT32 x1, x2, y1, y2; int srcPitch, srcPitch2 = 0, dstPitch, destId; @@ -2700,7 +2701,7 @@ I830DisplaySurface(XF86SurfacePtr surface, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn); I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset); INT32 x1, y1, x2, y2; INT32 loops = 0; BoxRec dstBox; diff --git a/src/i830_xaa.c b/src/i830_xaa.c index 5ef5d3c4..f0951387 100644 --- a/src/i830_xaa.c +++ b/src/i830_xaa.c @@ -162,20 +162,20 @@ I830XAAInit(ScreenPtr pScreen) /* On the primary screen */ if (pI830->init == 0) { - if (pI830->Scratch.Size != 0) { + if (pI830->xaa_scratch->size != 0) { width = ((pScrn->displayWidth + 31) & ~31) / 8; - nr_buffers = pI830->Scratch.Size / width; - ptr = pI830->FbBase + pI830->Scratch.Start; + nr_buffers = pI830->xaa_scratch->size / width; + ptr = pI830->FbBase + pI830->xaa_scratch->offset; } } else { /* On the secondary screen */ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - if (pI8301->Scratch2.Size != 0) { + if (pI8301->xaa_scratch_2->size != 0) { width = ((pScrn->displayWidth + 31) & ~31) / 8; - nr_buffers = pI8301->Scratch2.Size / width; + nr_buffers = pI8301->xaa_scratch_2->size / width; /* We have to use the primary screen's FbBase, as that's where - * we allocated Scratch2, so we get the correct pointer */ - ptr = pI8301->FbBase + pI8301->Scratch2.Start; + * we allocated xaa_scratch_2, so we get the correct pointer */ + ptr = pI8301->FbBase + pI8301->xaa_scratch_2->offset; } } @@ -279,11 +279,15 @@ CheckTiling(ScrnInfoPtr pScrn) if (IS_I965G(pI830)) { if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR) tiled = 1; - if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR) + if (pI830->bufferOffset == pI830->back_buffer->offset && + pI830->back_tiled == FENCE_XMAJOR) { tiled = 1; + } /* not really supported as it's always YMajor tiled */ - if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR) + if (pI830->bufferOffset == pI830->depth_buffer->offset && + pI830->depth_tiled == FENCE_XMAJOR) { tiled = 1; + } } return tiled; @@ -600,7 +604,7 @@ I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); /* We have to use the primary screen's FbBase, as that's where - * we allocated Scratch2, so we get the correct pointer */ + * we allocated xaa_scratch_2, so we get the correct pointer */ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - pI8301->FbBase); } @@ -700,7 +704,7 @@ I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); /* We have to use the primary screen's FbBase, as that's where - * we allocated Scratch2, so we get the correct pointer */ + * we allocated xaa_scratch_2, so we get the correct pointer */ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - pI8301->FbBase); } diff --git a/src/i965_render.c b/src/i965_render.c index 5c3f61d6..78f1146c 100644 --- a/src/i965_render.c +++ b/src/i965_render.c @@ -501,9 +501,9 @@ i965_prepare_composite(int op, PicturePtr pSrcPicture, next_offset = default_color_offset + sizeof(*default_color_state); total_state_size = next_offset; - assert(total_state_size < EXA_LINEAR_EXTRA); + assert(total_state_size < pI830->exa_965_state->size); - state_base_offset = pI830->EXAStateMem.Start; + state_base_offset = pI830->exa_965_state->offset; state_base_offset = ALIGN(state_base_offset, 64); state_base = (char *)(pI830->FbBase + state_base_offset); |