xf86-video-intel: Branch 'modesetting' - src/i830_driver.c src/i830_memory.c src/i830_video.c src/i830_video.h

Eric Anholt anholt at kemper.freedesktop.org
Wed Dec 27 23:54:59 EET 2006


 src/i830_driver.c |   34 ++--
 src/i830_memory.c |  399 ++++++++++++++++++++++--------------------------------
 src/i830_video.c  |  199 ++++++++++++++++++--------
 src/i830_video.h  |   15 +-
 4 files changed, 333 insertions(+), 314 deletions(-)

New commits:
diff-tree 46df75ccd4647ea033583130253a2a2218b34a20 (from 84915ac8afeb4bbc03df8f94ab3ba351788d6501)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 13:45:06 2006 -0800

    Bug #7524: Major improvements to EXA/XAA static memory allocation.
    
    With this, we no longer allocate XV through the XF86 linear allocator in the
    EXA case.  We also no longer allocate extra space for the XF86 2D allocator
    that we don't use in EXA mode, or space for the EXA allocator in XAA mode.
    The EXA offscreen allocator now gets enough space for several screenfuls of
    pixmaps plus one 1920x1088 movie.
    
    A large duplicated section of code for allocating each framebuffer in the old
    dual-screen mode was also factored out.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index d30af07..e2653c1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2855,20 +2855,28 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    DPRINTF(PFX,
 	   "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
-   if (I830IsPrimary(pScrn)) {
-      if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Failed to init memory manager\n");
-      }
-
-      if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, pI830->LinearMem.Offset / pI830->cpp, pI830->LinearMem.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);
+   if (!pI830->useEXA) {
+      if (I830IsPrimary(pScrn)) {
+	 if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to init memory manager\n");
+	 }
 
-   } else {
-      if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Failed to init memory manager\n");
+	 if (pI830->LinearAlloc &&
+	     xf86InitFBManagerLinear(pScreen,
+				     pI830->LinearMem.Offset / pI830->cpp,
+				     pI830->LinearMem.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);
+	 }
+      } else {
+	 if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to init memory manager\n");
+	 }
       }
    }
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 7b0c6fe..b41a73d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -602,11 +602,141 @@ GetFreeSpace(ScrnInfoPtr pScrn)
    return extra;
 }
 
+/**
+ * Allocates a framebuffer for a screen.
+ *
+ * Used once for each X screen, so once with RandR 1.2 and twice with classic
+ * dualhead.
+ *
+ * \param pScrn ScrnInfoPtr for the screen being allocated
+ * \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)
+{
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   unsigned long minspace, avail, lineSize;
+   int cacheLines, maxCacheLines;
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   Bool tileable;
+   int align, alignflags;
+   long size, alloced, fb_height;
+
+   /* 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.
+    */
+   if (pScrn->virtualX > pScrn->virtualY)
+      fb_height = pScrn->virtualX;
+   else
+      fb_height = pScrn->virtualY;
+
+   FbMemBox->x1 = 0;
+   FbMemBox->x2 = pScrn->displayWidth;
+   FbMemBox->y1 = 0;
+   FbMemBox->y2 = fb_height;
+
+   /* 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 if we're using XAA.
+    */
+
+   lineSize = pScrn->displayWidth * pI830->cpp;
+   minspace = lineSize * pScrn->virtualY;
+   avail = pScrn->videoRam * 1024;
+
+   if (!pI830->useEXA) {
+      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;
+
+      FbMemBox->y2 += cacheLines;
+
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		     "%sAllocating at least %d scanlines for pixmap cache\n",
+		     s, cacheLines);
+   } else {
+     /* For EXA, we have a separate allocation for the linear allocator which
+      * also does the pixmap cache.
+      */
+     cacheLines = 0;
+   }
+
+   tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
+      IsTileable(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;
+   }
+
+   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 (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+		    "%sframebuffer. Is your VideoRAM set too low?\n",
+		    secondary ? "secondary " : "");
+      }
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
  */
-
 Bool
 I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
 {
@@ -648,8 +778,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	   pI830->StolenPool.Free.Size);
 
    if (flags & ALLOC_INITIAL) {
-      unsigned long minspace, avail, lineSize;
-      int cacheLines, maxCacheLines;
 
       if (pI830->NeedRingBufferLow)
 	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);
@@ -660,242 +788,45 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
          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) {
-            if (IS_I9XX(pI830))
-               align = MB(1);
-            else
-	       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) {
-         if (IS_I9XX(pI830))
-            align = MB(1);
-         else
-	    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");
+	 if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302,
+				      &pI830->FbMemBox2,
+				      &pI830->FrontBuffer2, &pI830->StolenPool,
+				      TRUE, flags))
+	 {
+	    return FALSE;
 	 }
-	 return FALSE;
       }
-#ifdef I830_USE_EXA
-      size = lineSize * pScrn->virtualY;
-      size = ROUND_TO_PAGE(size);
-
-      if (tileable) {
-	 align = KB(512);
-	 alignflags = ALIGN_BOTH_ENDS;
-      } else {
-	 align = KB(64);
-	 alignflags = 0;
+      if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox,
+				   &pI830->FrontBuffer, &pI830->StolenPool,
+				   FALSE, flags))
+      {
+	 return FALSE;
       }
 
-      alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen),
-				&(pI830->StolenPool), size, align,
-				flags | alignflags |
-				FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-		       "offscreen memory.  Not enough VRAM?\n");
+#ifdef I830_USE_EXA
+      if (pI830->useEXA) {
+	 /* Default EXA to having 3 screens worth of offscreen memory space
+	  * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
+	  */
+	 size = 3 * pScrn->displayWidth * pI830->cpp * 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) {
+	    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);
 	 }
-	 return FALSE;
-      } else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate "
-		       "offscreen memory at 0x%lx, size %ld KB\n", 
-			pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
       }
 #endif
    } else {
diff --git a/src/i830_video.c b/src/i830_video.c
index d10fd16..946a447 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -120,8 +120,8 @@ static int I830QueryImageAttributesTextu
 
 static void I830BlockHandler(int, pointer, pointer, pointer);
 
-static FBLinearPtr
-I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
+static void
+I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear);
 
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
@@ -715,7 +715,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    pPriv->contrast = 64;
    pPriv->saturation = 128;
    pPriv->pipe = 0;  /* XXX must choose pipe wisely */
-   pPriv->linear = NULL;
+   memset(&pPriv->linear, 0, sizeof(pPriv->linear));
    pPriv->currentBuf = 0;
    pPriv->gamma5 = 0xc0c0c0;
    pPriv->gamma4 = 0x808080;
@@ -838,7 +838,7 @@ I830SetupImageVideoTextured(ScreenPtr pS
 
       pPriv->textured = TRUE;
       pPriv->videoStatus = 0;
-      pPriv->linear = NULL;
+      memset(&pPriv->linear, 0, sizeof(pPriv->linear));
       pPriv->currentBuf = 0;
       pPriv->doubleBuffer = 0;
 
@@ -902,10 +902,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
          if (pI830->entityPrivate)
             pI830->entityPrivate->XvInUse = -1;
       }
-      if (pPriv->linear) {
-	 xf86FreeOffscreenLinear(pPriv->linear);
-	 pPriv->linear = NULL;
-      }
+      I830FreeMemory(pScrn, &pPriv->linear);
       pPriv->videoStatus = 0;
    } else {
       if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
@@ -2224,9 +2221,7 @@ BroadwaterDisplayVideoTextured(ScrnInfoP
    /*
     * Use the extra space allocated at the end of the Xv buffer
     */
-   state_base_offset = (pPriv->YBuf0offset + 
-			pPriv->linear->size * pI830->cpp -
-			BRW_LINEAR_EXTRA);
+   state_base_offset = pPriv->extra_offset;
    state_base_offset = ALIGN(state_base_offset, 64);
 
    state_base = (char *)(pI830->FbBase + state_base_offset);
@@ -2798,44 +2793,119 @@ BroadwaterDisplayVideoTextured(ScrnInfoP
 #endif
 }
 
-static FBLinearPtr
-I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
+#ifdef I830_USE_EXA
+static void
+I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
+{
+   struct linear_alloc *linear = area->privData;
+
+   linear->exa = NULL;
+   linear->offset = 0;
+}
+#endif /* I830_USE_EXA */
+
+/**
+ * Allocates linear memory using the XFree86 (XAA) or EXA allocator.
+ *
+ * \param pPriv adaptor the memory is being allocated for.
+ * \param size size of the allocation, in bytes.
+ * \param alignment offset alignment of the allocation, in bytes.
+ * \return offset of the allocated memory.
+ */
+static void
+I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size,
+		   int align)
 {
-   ScreenPtr pScreen;
-   FBLinearPtr new_linear = NULL;
+   ScreenPtr pScreen = pScrn->pScreen;
+   I830Ptr pI830 = I830PTR(pScrn);
 
-   if (linear) {
-      if (linear->size >= size)
-	 return linear;
+#ifdef I830_USE_EXA
+   if (pI830->useEXA) {
+      if (linear->exa != NULL) {
+	 if (linear->exa->size >= size)
+	    return;
 
-      if (xf86ResizeOffscreenLinear(linear, size))
-	 return linear;
+	 exaOffscreenFree(pScreen, linear->exa);
+	 linear->offset = 0;
+      }
 
-      xf86FreeOffscreenLinear(linear);
+      linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE,
+				      I830VideoSave, linear);
+      if (linear->exa == NULL)
+	 return;
+      linear->offset = linear->exa->offset;
    }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+   if (!pI830->useEXA) {
+      int max_size;
 
-   pScreen = screenInfo.screens[pScrn->scrnIndex];
+      /* The XFree86 linear allocator operates in units of screen pixels,
+       * sadly.
+       */
+      size = (size + pI830->cpp - 1) / pI830->cpp;
+      align = (align + pI830->cpp - 1) / pI830->cpp;
 
-   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
-					    NULL, NULL, NULL);
+      if (linear->xaa != NULL) {
+	 if (linear->xaa->size >= size) {
+	    linear->offset = linear->xaa->offset * pI830->cpp;
+	    return;
+	 }
 
-   if (!new_linear) {
-      int max_size;
+	 if (xf86ResizeOffscreenLinear(linear->xaa, size)) {
+	    linear->offset = linear->xaa->offset * pI830->cpp;
+	    return;
+	 }
+
+	 xf86FreeOffscreenLinear(linear->xaa);
+      }
+
+      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
+						NULL, NULL, NULL);
+      if (linear->xaa != NULL) {
+	 linear->offset = linear->xaa->offset * pI830->cpp;
+	 return;
+      }
 
-      xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4,
+      xf86QueryLargestOffscreenLinear(pScreen, &max_size, align,
 				      PRIORITY_EXTREME);
 
       if (max_size < size) {
-         ErrorF("No memory available\n");
-	 return NULL;
+	 ErrorF("No memory available\n");
+	 linear->offset = 0;
+	 return;
       }
 
       xf86PurgeUnlockedOffscreenAreas(pScreen);
-      new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
-					       NULL, NULL, NULL);
+      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4,
+						NULL, NULL, NULL);
+      linear->offset = linear->xaa->offset * pI830->cpp;
    }
+#endif /* I830_USE_XAA */
+}
 
-   return new_linear;
+static void
+I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef I830_USE_EXA
+   if (pI830->useEXA) {
+      if (linear->exa != NULL) {
+	 exaOffscreenFree(pScrn->pScreen, linear->exa);
+	 linear->exa = NULL;
+      }
+   }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+   if (!pI830->useEXA) {
+      if (linear->xaa != NULL) {
+	 xf86FreeOffscreenLinear(linear->xaa);
+	 linear->xaa = NULL;
+      }
+   }
+#endif /* I830_USE_XAA */
+   linear->offset = 0;
 }
 
 /*
@@ -2981,19 +3051,21 @@ I830PutImage(ScrnInfoPtr pScrn,
       extraLinear = 0;
 
    /* size is multiplied by 2 because we have two buffers that are flipping */
-   pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear,
-				      (extraLinear +
-				       (pPriv->doubleBuffer ? size * 2 : size)) /
-				      pI830->cpp);
+   I830AllocateMemory(pScrn, &pPriv->linear,
+		      extraLinear + (pPriv->doubleBuffer ? size * 2 : size),
+		      16);
 
-   if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY))
+   if (pPriv->linear.offset == 0)
       return BadAlloc;
 
+   pPriv->extra_offset = pPriv->linear.offset +
+      pPriv->doubleBuffer ? size * 2 : size;
+
    /* fixup pointers */
 #if 0
-   pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp;
+   pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear.offset;
 #else
-   pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp;
+   pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear.offset;
 #endif
    if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
       pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width);
@@ -3236,10 +3308,7 @@ I830BlockHandler(int i,
 	 }
       } else {				/* FREE_TIMER */
 	 if (pPriv->freeTime < now) {
-	    if (pPriv->linear) {
-	       xf86FreeOffscreenLinear(pPriv->linear);
-	       pPriv->linear = NULL;
-	    }
+	    I830FreeMemory(pScrn, &pPriv->linear);
 	    pPriv->videoStatus = 0;
 	 }
       }
@@ -3251,7 +3320,7 @@ I830BlockHandler(int i,
  ***************************************************************************/
 
 typedef struct {
-   FBLinearPtr linear;
+   struct linear_alloc linear;
    Bool isOn;
 } OffscreenPrivRec, *OffscreenPrivPtr;
 
@@ -3261,8 +3330,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
 		    unsigned short w,
 		    unsigned short h, XF86SurfacePtr surface)
 {
-   FBLinearPtr linear;
-   int pitch, fbpitch, size, bpp;
+   int pitch, fbpitch, size;
    OffscreenPrivPtr pPriv;
    I830Ptr pI830 = I830PTR(pScrn);
 
@@ -3280,41 +3348,40 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
    if (pI830->rotation != RR_Rotate_0)
       return BadAlloc;
 
-   w = (w + 1) & ~1;
-   pitch = ((w << 1) + 15) & ~15;
-   bpp = pScrn->bitsPerPixel >> 3;
-   fbpitch = bpp * pScrn->displayWidth;
-   size = ((pitch * h) + bpp - 1) / bpp;
-
-   if (!(linear = I830AllocateMemory(pScrn, NULL, size)))
+   if (!(surface->pitches = xalloc(sizeof(int))))
       return BadAlloc;
-
-   surface->width = w;
-   surface->height = h;
-
-   if (!(surface->pitches = xalloc(sizeof(int)))) {
-      xf86FreeOffscreenLinear(linear);
-      return BadAlloc;
-   }
    if (!(surface->offsets = xalloc(sizeof(int)))) {
       xfree(surface->pitches);
-      xf86FreeOffscreenLinear(linear);
       return BadAlloc;
    }
    if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
       xfree(surface->pitches);
       xfree(surface->offsets);
-      xf86FreeOffscreenLinear(linear);
       return BadAlloc;
    }
 
-   pPriv->linear = linear;
+   w = (w + 1) & ~1;
+   pitch = ((w << 1) + 15) & ~15;
+   fbpitch = pI830->cpp * pScrn->displayWidth;
+   size = pitch * h;
+
+   I830AllocateMemory(pScrn, &pPriv->linear, size, 16);
+   if (pPriv->linear.offset == 0) {
+      xfree(surface->pitches);
+      xfree(surface->offsets);
+      xfree(pPriv);
+      return BadAlloc;
+   }
+
+   surface->width = w;
+   surface->height = h;
+
    pPriv->isOn = FALSE;
 
    surface->pScrn = pScrn;
    surface->id = id;
    surface->pitches[0] = pitch;
-   surface->offsets[0] = linear->offset * bpp;
+   surface->offsets[0] = pPriv->linear.offset;
    surface->devPrivate.ptr = (pointer) pPriv;
 
 #if 0
@@ -3358,7 +3425,7 @@ I830FreeSurface(XF86SurfacePtr surface)
    if (pPriv->isOn) {
       I830StopSurface(surface);
    }
-   xf86FreeOffscreenLinear(pPriv->linear);
+   I830FreeMemory(surface->pScrn, &pPriv->linear);
    xfree(surface->pitches);
    xfree(surface->offsets);
    xfree(surface->devPrivate.ptr);
diff --git a/src/i830_video.h b/src/i830_video.h
index 6a09a25..12a5bda 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -27,6 +27,18 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 #include "xf86.h"
 #include "xf86_OSproc.h"
 
+/* Ugly mess to support the old XF86 allocator or EXA using the same code.
+ */
+struct linear_alloc {
+#ifdef I830_USE_XAA
+   FBLinearPtr xaa;
+#endif
+#ifdef I830_USE_EXA
+   ExaOffscreenArea *exa;
+#endif
+   unsigned int offset;
+};
+
 typedef struct {
    CARD32 YBuf0offset;
    CARD32 UBuf0offset;
@@ -57,7 +69,8 @@ typedef struct {
    CARD32 videoStatus;
    Time offTime;
    Time freeTime;
-   FBLinearPtr linear;
+   struct linear_alloc linear;
+   unsigned int extra_offset;
 
    Bool overlayOK;
    int oneLineMode;



More information about the xorg-commit mailing list