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 diff --git a/src/i830.h b/src/i830.h index f52f1496..f779978c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -113,40 +113,58 @@ 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; +/** 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; -typedef struct _I830MemPool { - I830MemRange Total; - I830MemRange Free; - I830MemRange Fixed; - I830MemRange Allocated; -} I830MemPool; + /** 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; int space; } I830RingBuffer; -typedef struct { - unsigned int Fence[FENCE_NEW_NR * 2]; -} I830RegRec, *I830RegPtr; - typedef struct { int lastInstance; int refCount; @@ -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); +Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn, const int flags); +Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn, const int flags); -extern void I830PrintAllRegisters(I830RegPtr i830Reg); -extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg); - -extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer); 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,6 +1375,40 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam = 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, + "/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) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "VideoRam reduced to %d kByte (limited to aperture " + "size)\n", + pScrn->videoRam); + } + } + /* Make sure it's on a page boundary */ if (pScrn->videoRam & 3) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB " @@ -1407,46 +1417,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) 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) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "VideoRAM reduced to %d kByte " - "(limited to available sysmem)\n", pScrn->videoRam); - } + 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; } - if (pScrn->videoRam > pI830->FbMapSize / 1024) { - pScrn->videoRam = pI830->FbMapSize / 1024; - if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "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); - - /* - * 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; - } + 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))) { @@ -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 */ +/** + * @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)) -static unsigned long -GetBestTileAlignment(unsigned long size) -{ - unsigned long i; +enum tile_format { + TILING_NONE, + TILING_XMAJOR, + TILING_YMAJOR +}; - for (i = KB(512); i < size; i <<= 1) - ; +static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset, + unsigned int pitch, unsigned int size, + enum tile_format tile_format); - if (i > MB(64)) - i = MB(64); - - return i; -} - -/* - * Allocate memory from the given pool. Grow the pool if needed and if - * possible. +/** + * Returns the fence size for a tiled area of the given size. */ static unsigned long -AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool, - long size, unsigned long alignment, int flags) +i830_get_fence_size(ScrnInfoPtr pScrn, unsigned long size) { I830Ptr pI830 = I830PTR(pScrn); - long needed, start, end; - Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + unsigned long i; + unsigned long start; - 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 (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; - - 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; + if (IS_I965G(pI830)) { + /* The 965 can have fences at any page boundary. */ + return ALIGN(size, GTT_PAGE_SIZE); } else { - result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment); - pool->Free.End -= needed; - result->End = result->Start + needed; - } - 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) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned long start, end; - unsigned long newApStart, newApEnd; - Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - - if (!result || !size) - return 0; - - 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; - } - - if (size > pI830->FreeMemory) { - if (dryrun) - pI830->FreeMemory = size; - else - return 0; - } - - /* 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 { - 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; - } - - if (!dryrun) { - if (newApStart > newApEnd) - return 0; - - if (flags & NEED_PHYSICAL_ADDR) { - result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, - &(result->Physical)); - } else { - result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, - NULL); - } - - if (result->Key == -1) - return 0; - } - - 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; -} - -void -I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range) -{ - I830Ptr pI830 = I830PTR(pScrn); - - if (!range || range->Size == 0) - return; - - if (range->Key != -1) - xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key); - - 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... + /* Align the size to a power of two greater than the smallest fence + * size. */ - I830MemPool *Pool = range->Pool; - Pool->Total.End = pI830->StolenMemory.End; - - if (pI830->StolenOnly) - Pool->Free.End += range->Size; + if (IS_I9XX(pI830)) + start = MB(1); else - Pool->Free.End = Pool->Total.End; + start = KB(512); - if (Pool->Free.End < Pool->Free.Start) { - Pool->Free.End = Pool->Free.Start; - } + for (i = start; i < size; i <<= 1) + ; - Pool->Free.Size = Pool->Free.End - Pool->Free.Start; - Pool->Total.Size = Pool->Total.End - Pool->Total.Start; - - if (!pI830->StolenOnly) { - pI830->FreeMemory -= Pool->Free.Size; - pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size); - pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size); - } - } else { - if (range->Alignment == GTT_PAGE_SIZE) - pI830->MemoryAperture.End = range->End; - else { - pI830->MemoryAperture.End = range->End - range->Size + - range->Alignment; - } - pI830->MemoryAperture.Size = pI830->MemoryAperture.End - - pI830->MemoryAperture.Start; - } - - if (!pI830->StolenOnly) - pI830->FreeMemory += range->Size; - pI830->allocatedMemory -= range->Size; -} - -unsigned long -I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool, - long size, unsigned long alignment, int flags) -{ - I830Ptr pI830 = I830PTR(pScrn); - Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); - - if (!result) - return 0; - - /* Make sure these are initialised. */ - result->Size = 0; - result->Key = -1; - - if (!size) { - return 0; - } - - 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; + return i; } } static Bool -AllocateRingBuffer(ScrnInfoPtr pScrn, int flags) +i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem) { 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 (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired) 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; + if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) { + mem->bound = TRUE; + return TRUE; + } else { + return FALSE; + } - alloced = I830AllocVidMem(pScrn, &(pI830->LpRing->mem), - &(pI830->StolenPool), size, - GTT_PAGE_SIZE, flags); - if (alloced < size) { + return TRUE; +} + +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 { + return FALSE; + } +} + +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); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + /* 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); + + /* 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; + } + + 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; + } + + 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) + 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; + + return mem; +} + +/** + * 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 (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; + } + + return TRUE; +} + + +/* 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) +{ + i830_memory *mem; + + mem = i830_allocate_aperture(pScrn, name, size, alignment, flags); + if (mem == NULL) + return NULL; + + if (!i830_allocate_agp_memory(pScrn, mem, flags)) { + i830_free_memory(pScrn, mem); + return NULL; + } + + return mem; +} + +/* 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 (tile_format == TILING_NONE) + return i830_allocate_memory(pScrn, name, size, alignment, flags); + + /* Check for maximum tiled region size */ + if (IS_I9XX(pI830)) { + if (size > MB(128)) + return NULL; + } else { + if (size > MB(64)) + return NULL; + } + + aper_size = i830_get_fence_size(pScrn, size); + if (IS_I965G(pI830)) { + aper_align = GTT_PAGE_SIZE; + } else { + /* 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); + } + } + + 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 " : ""); +} + +void +i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix) +{ + I830Ptr pI830 = I830PTR(pScrn); + i830_memory *mem; + + if (pI830->memory_list == NULL) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sMemory allocator not initialized\n", prefix); + return; + } + + if (pI830->memory_list->next->next == NULL) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sNo memory allocations\n", prefix); + return; + } + + 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); + + 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 +i830_allocate_ringbuffer(ScrnInfoPtr pScrn, int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + + if (pI830->noAccel || pI830->LpRing->mem != NULL) + return TRUE; + + 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 (!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. */ + } + } } - 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); - } - - /* 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"); + 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"); + } } - } 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); - } - 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. + /* 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. */ - - 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; - } + 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; + } +#endif /* I830_USE_EXA */ - /* - * 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 (flags & ALLOC_INITIAL) { - if (extra == 0) - return TRUE; + /* 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); - 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); + pI830->front_buffer_2 = + i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302, + &pI830->FbMemBox2, + TRUE, flags); + if (pI830->front_buffer_2 == NULL) 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; - } - -#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 (!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; - } - } - } - -#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"); - } + pI830->front_buffer = + i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, + FALSE, flags); + if (pI830->front_buffer == NULL) return FALSE; + } + + 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; + } + } } - 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)); + + 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; } - 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; - } + /* 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) { - /* 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); - } - 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); - if (nr < 0 || nr > 7) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetFence: fence %d out of range\n",nr); + assert(tile_format != TILING_NONE); + + 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; } - i830Reg->Fence[nr] = 0; + if (nr < 0 || nr >= FENCE_NR) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "i830_set_fence(): fence %d out of range\n",nr); + return; + } + + pI830->fence[nr] = 0; if (IS_I9XX(pI830)) fence_mask = ~I915G_FENCE_START_MASK; else fence_mask = ~I830_FENCE_START_MASK; - if (start & fence_mask) { + 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 + pI830->gtt_acquired = TRUE; - 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; - - 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; + 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); + } } - 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; - } -#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);