i830_memory.c
来自「是由intel提供的针对intel显卡915以上系列的linux驱动」· C语言 代码 · 共 1,966 行 · 第 1/4 页
C
1,966 行
align = GTT_PAGE_SIZE; alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); } if (alloced < size) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate rotated buffer space.\n"); } return FALSE; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sAllocated %ld kB for the rotated buffer at 0x%lx.\n", s, alloced / 1024, pI830->RotatedMem.Start); return TRUE;}BoolI830AllocateRotated2Buffer(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] " : ""; int align; Bool tileable; int lines; I830EntPtr pI830Ent = pI830->entityPrivate; I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); int height = (pI8302->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pI830Ent->pScrn_2->virtualY : pI830Ent->pScrn_2->virtualX; /* Rotated Buffer */ memset(&(pI830->RotatedMem2), 0, sizeof(I830MemRange)); pI830->RotatedMem2.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; } else { lines = height; } size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * lines * pI8302->cpp); /* * Try to allocate on the best tile-friendly boundaries. */ alloced = 0; if (tileable) { align = GetBestTileAlignment(size); for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | ALIGN_BOTH_ENDS); if (alloced >= size) break; } } if (alloced < size) { /* Give up on trying to tile */ tileable = FALSE; size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * height * pI8302->cpp); align = GTT_PAGE_SIZE; alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); } if (alloced < size) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate rotated2 buffer space.\n"); } return FALSE; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sAllocated %ld kB for the rotated2 buffer at 0x%lx.\n", s, alloced / 1024, pI830->RotatedMem2.Start); return TRUE;}static unsigned longGetFreeSpace(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;}/* * Allocate memory for 2D operation. This includes the (front) framebuffer, * ring buffer, scratch memory, HW cursor. */BoolI830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags){ I830Ptr pI830 = I830PTR(pScrn); long size, alloced; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); int verbosity = dryrun ? 4 : 1; const char *s = dryrun ? "[dryrun] " : ""; Bool tileable; int align, alignflags; DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n", BOOLTOSTRING(flags & ALLOC_INITIAL)); if (!pI830->StolenOnly && (!I830AgpGARTSupported() || !I830AcquireGART(pScrn->scrnIndex))) { if (!dryrun) { 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"); } return FALSE; } /* * The I830 is slightly different from the I830/I815, it has no * dcache and it has stolen memory by default in its gtt. All * additional memory must go after it. */ DPRINTF(PFX, "size == %luk (%lu bytes == pScrn->videoRam)\n" "pI830->StolenSize == %luk (%lu bytes)\n", pScrn->videoRam, pScrn->videoRam * 1024, pI830->StolenPool.Free.Size / 1024, pI830->StolenPool.Free.Size); if (flags & ALLOC_INITIAL) { unsigned long minspace, avail, lineSize; int cacheLines, maxCacheLines; 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); /* Clear everything first. */ memset(&(pI830->FbMemBox2), 0, sizeof(pI830->FbMemBox2)); memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2)); pI830->FrontBuffer2.Key = -1;#if 1 /* ROTATION */ pI830->FbMemBox2.x1 = 0; pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; pI830->FbMemBox2.y1 = 0; if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX; else pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY;#else pI830->FbMemBox2.x1 = 0; pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; pI830->FbMemBox2.y1 = 0; pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY;#endif /* * Calculate how much framebuffer memory to allocate. For the * initial allocation, calculate a reasonable minimum. This is * enough for the virtual screen size, plus some pixmap cache * space. */ lineSize = pI830Ent->pScrn_2->displayWidth * pI8302->cpp; minspace = lineSize * pI830Ent->pScrn_2->virtualY; avail = pI830Ent->pScrn_2->videoRam * 1024; maxCacheLines = (avail - minspace) / lineSize; /* This shouldn't happen. */ if (maxCacheLines < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal Error: " "maxCacheLines < 0 in I830Allocate2DMemory()\n"); maxCacheLines = 0; } if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY)) maxCacheLines = MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY; if (pI8302->CacheLines >= 0) { cacheLines = pI8302->CacheLines; } else {#if 1 /* Make sure there is enough for two DVD sized YUV buffers */ cacheLines = (pI830Ent->pScrn_2->depth == 24) ? 256 : 384; if (pI830Ent->pScrn_2->displayWidth <= 1024) cacheLines *= 2;#else /* * Make sure there is enough for two DVD sized YUV buffers. * Make that 1.5MB, which is around what was allocated with * the old algorithm */ cacheLines = (MB(1) + KB(512)) / pI8302->cpp / pI830Ent->pScrn_2->displayWidth;#endif } if (cacheLines > maxCacheLines) cacheLines = maxCacheLines; pI830->FbMemBox2.y2 += cacheLines; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sAllocating at least %d scanlines for pixmap cache\n", s, cacheLines); tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip && IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); if (tileable) { align = KB(512); alignflags = ALIGN_BOTH_ENDS; } else { align = KB(64); alignflags = 0; }#if 1 /* ROTATION */ if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines); else size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); size = ROUND_TO_PAGE(size);#else size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); size = ROUND_TO_PAGE(size);#endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sSecondary framebuffer allocation size: %ld kByte\n", s, size / 1024); alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer2), &(pI830->StolenPool), size, align, flags | alignflags | FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); if (alloced < size) { if (!dryrun) { xf86DrvMsg(pI830Ent->pScrn_2->scrnIndex, X_ERROR, "Failed to allocate secondary framebuffer.\n"); } return FALSE; } } /* Clear everything first. */ memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox)); memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); pI830->FrontBuffer.Key = -1;#if 1 /* ROTATION */ pI830->FbMemBox.x1 = 0; pI830->FbMemBox.x2 = pScrn->displayWidth; pI830->FbMemBox.y1 = 0; if (pScrn->virtualX > pScrn->virtualY) pI830->FbMemBox.y2 = pScrn->virtualX; else pI830->FbMemBox.y2 = pScrn->virtualY;#else pI830->FbMemBox.x1 = 0; pI830->FbMemBox.x2 = pScrn->displayWidth; pI830->FbMemBox.y1 = 0; pI830->FbMemBox.y2 = pScrn->virtualY;#endif /* * Calculate how much framebuffer memory to allocate. For the * initial allocation, calculate a reasonable minimum. This is * enough for the virtual screen size, plus some pixmap cache * space. */ lineSize = pScrn->displayWidth * pI830->cpp; minspace = lineSize * pScrn->virtualY; avail = pScrn->videoRam * 1024; maxCacheLines = (avail - minspace) / lineSize; /* This shouldn't happen. */ if (maxCacheLines < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal Error: " "maxCacheLines < 0 in I830Allocate2DMemory()\n"); maxCacheLines = 0; } if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY)) maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY; if (pI830->CacheLines >= 0) { cacheLines = pI830->CacheLines; } else {#if 1 /* Make sure there is enough for two DVD sized YUV buffers */ cacheLines = (pScrn->depth == 24) ? 256 : 384; if (pScrn->displayWidth <= 1024) cacheLines *= 2;#else /* * Make sure there is enough for two DVD sized YUV buffers. * Make that 1.5MB, which is around what was allocated with * the old algorithm */ cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth;#endif } if (cacheLines > maxCacheLines) cacheLines = maxCacheLines; pI830->FbMemBox.y2 += cacheLines; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sAllocating at least %d scanlines for pixmap cache\n", s, cacheLines); tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && IsTileable(pScrn->displayWidth * pI830->cpp); if (tileable) { align = KB(512); alignflags = ALIGN_BOTH_ENDS; } else { align = KB(64); alignflags = 0; }#if 1 /* ROTATION */ if (pScrn->virtualX > pScrn->virtualY) size = lineSize * (pScrn->virtualX + cacheLines); else size = lineSize * (pScrn->virtualY + cacheLines); size = ROUND_TO_PAGE(size);#else size = lineSize * (pScrn->virtualY + cacheLines); size = ROUND_TO_PAGE(size);#endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sInitial framebuffer allocation size: %ld kByte\n", s, size / 1024); alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), &(pI830->StolenPool), size, align, flags | alignflags | FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); if (alloced < size) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " "framebuffer. Is your VideoRAM set too low ??\n"); } return FALSE; } } else { long lineSize; long extra = 0; long maxFb = 0; /* * XXX Need to "free" up any 3D allocations if the DRI ended up * and make them available for 2D. The best way to do this would * be position all of those regions contiguously at the end of the * StolenPool. */ extra = GetFreeSpace(pScrn); if (extra == 0) return TRUE; maxFb = pI830->FrontBuffer.Size + extra; lineSize = pScrn->displayWidth * pI830->cpp; maxFb = ROUND_DOWN_TO(maxFb, lineSize); if (maxFb > lineSize * MAX_DISPLAY_HEIGHT) maxFb = lineSize * MAX_DISPLAY_HEIGHT; if (0/*maxFb > pI830->FrontBuffer.Size*/) { unsigned long oldsize; /* * Sanity check -- the fb should be the last thing allocated at * the bottom of the stolen pool. */ if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error in I830Allocate2DMemory():\n\t" "Framebuffer isn't the last allocation at the bottom" " of StolenPool\n\t(%lx != %lx).\n", pI830->FrontBuffer.End, pI830->StolenPool.Free.Start); return FALSE; } /* * XXX Maybe should have a "Free" function. This should be * the only place where a region is resized, and we know that * the fb is always at the bottom of the aperture/stolen pool, * and is the only region that is allocated bottom-up. * Allowing for more general realloction would require a smarter * allocation system. */ oldsize = pI830->FrontBuffer.Size; pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size; pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sUpdated framebuffer allocation size from %ld " "to %ld kByte\n", s, oldsize / 1024, maxFb / 1024); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sUpdated pixmap cache from %ld scanlines to %ld " "scanlines\n", s, oldsize / lineSize - pScrn->virtualY, maxFb / lineSize - pScrn->virtualY); pI830->FbMemBox.y2 = maxFb / lineSize; tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && IsTileable(pScrn->displayWidth * pI830->cpp); if (tileable) { 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)); /* Due to a bug in agpgart in 2.6 kernels resulting in very poor * allocation performance we need to workaround it here... */ pI830->Dummy.Key = I830AllocateGARTMemory(pScrn->scrnIndex, size, 3, NULL); if (pI830->Dummy.Key == -1) pI830->Dummy.Key = I830AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL); pI830->Dummy.Offset = 0; }#endif /* Clear cursor info */ memset(pI830->CursorMem, 0, sizeof(I830MemRange)); pI830->CursorMem->Key = -1; memset(pI830->CursorMemARGB, 0, sizeof(I830MemRange)); pI830->CursorMemARGB->Key = -1; if (!pI830->SWCursor) { int cursFlags = 0; /* * 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; alloced = I830AllocVidMem(pScrn, pI830->CursorMem, &(pI830->StolenPool), size, GTT_PAGE_SIZE, flags | cursFlags); if (alloced < size) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate HW cursor space.\n"); } } else { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sAllocated %ld kB for HW cursor at 0x%lx", s, alloced / 1024, pI830->CursorMem->Start); if (pI830->CursorNeedsPhysical) xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMem->Physical);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?