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 + -
显示快捷键?