When running UXA (and not DRI1), we can resize the frame buffer.
Signed-off-by: Keith Packard <kei...@keithp.com>
---
 src/i830.h         |    9 +++
 src/i830_display.c |   29 ++++++++++-
 src/i830_display.h |    1 +
 src/i830_driver.c  |  143 ++++++++++++++++++++++++++++++++++++++-------------
 src/i830_exa.c     |   22 ++++++++
 src/i830_memory.c  |   17 ++++--
 6 files changed, 178 insertions(+), 43 deletions(-)

diff --git a/src/i830.h b/src/i830.h
index 8ad5c69..2ab8893 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -95,6 +95,7 @@ void i830_uxa_block_handler (ScreenPtr pScreen);
 
 #if defined(I830_USE_UXA) || defined(I830_USE_EXA)
 dri_bo *i830_get_pixmap_bo (PixmapPtr pixmap);
+void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo);
 #endif
 
 #ifdef I830_USE_XAA
@@ -271,6 +272,8 @@ typedef struct _I830CrtcPrivateRec {
     
     int                            dpms_mode;
     
+    int                            x, y;
+
     /* Lookup table values to be set when the CRTC is enabled */
     uint8_t lut_r[256], lut_g[256], lut_b[256];
 
@@ -474,6 +477,8 @@ typedef struct _I830Rec {
    int drmMinor;
    Bool allocate_classic_textures;
 
+   Bool can_resize;
+
    Bool want_vblank_interrupts;
 #ifdef DAMAGE
    DamagePtr pDamage;
@@ -910,6 +915,10 @@ Bool i830_unbind_all_memory(ScrnInfoPtr pScrn);
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
 
+i830_memory *
+i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
+                         Bool secondary);
+
 /* i830_modes.c */
 DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 2e5d55a..b1ce9e6 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -410,6 +410,9 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
        Start = pI8301->front_buffer_2->offset;
     }
 
+    crtc->x = x;
+    crtc->y = y;
+
     if (IS_I965G(pI830)) {
         OUTREG(dspbase, Offset);
        POSTING_READ(dspbase);
@@ -1642,10 +1645,34 @@ i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr 
rotate_pixmap, void *data)
 static void
 i830_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
 {
-    i830PipeSetBase(crtc, x, y);
+    if (crtc->enabled)
+       i830PipeSetBase(crtc, x, y);
 }
 #endif
 
+/* The screen bo has changed, reset each active crtc to point at
+ * the same location that it currently points at, but in the new bo
+ */
+void
+i830_set_new_crtc_bo(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int                        i;
+
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+       xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+       if (crtc->enabled) {
+           I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+           int plane = intel_crtc->plane;
+           int dspstride_reg = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
+            OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
+           i830PipeSetBase(crtc, crtc->x, crtc->y);
+       }
+    }
+}
+
 void
 i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
 {
diff --git a/src/i830_display.h b/src/i830_display.h
index 1eeb7f1..8d767b1 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -31,6 +31,7 @@
 void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
+void i830_set_new_crtc_bo(ScrnInfoPtr pScrn);
 
 xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, 
int *dpms_mode);
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7590257..d366ab6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1085,11 +1085,103 @@ I830IsPrimary(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
+
+/*
+ * Adjust *width to allow for tiling if possible
+ */
+static Bool
+i830_tiled_width(I830Ptr i830, int *width, int cpp)
+{
+    Bool    tiled = FALSE;
+
+    /*
+     * Adjust the display width to allow for front buffer tiling if possible
+     */
+    if (i830->tiling) {
+       if (IS_I965G(i830)) {
+           int tile_pixels = 512 / cpp;
+           *width = (*width + tile_pixels - 1) &
+               ~(tile_pixels - 1);
+           tiled = TRUE;
+       } else {
+           /* Good pitches to allow tiling.  Don't care about pitches < 1024
+            * pixels.
+            */
+           static const int pitches[] = {
+               1024,
+               2048,
+               4096,
+               8192,
+               0
+           };
+           int i;
+
+           for (i = 0; pitches[i] != 0; i++) {
+               if (pitches[i] >= *width) {
+                   *width = pitches[i];
+                   tiled = TRUE;
+                   break;
+               }
+           }
+       }
+    }
+    return tiled;
+}
+
+/*
+ * Pad to accelerator requirement
+ */
+static int
+i830_pad_drawable_width(int width)
+{
+    return (width + 63) & ~63;
+}
+
 static Bool
 i830_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 {
+    I830Ptr    i830 = I830PTR(scrn);
+    int                old_x = scrn->virtualX;
+    int                old_y = scrn->virtualY;
+    int                old_width = scrn->displayWidth;
+
+    if (old_x == width && old_y == height)
+       return TRUE;
+
     scrn->virtualX = width;
     scrn->virtualY = height;
+#ifdef DRI2
+    if (i830->can_resize && i830->front_buffer)
+    {
+       i830_memory *new_front;
+       BoxRec      mem_box;
+       Bool        tiled;
+       ScreenPtr   screen = screenInfo.screens[scrn->scrnIndex];
+
+       scrn->displayWidth = i830_pad_drawable_width(width);
+       tiled = i830_tiled_width(i830, &scrn->displayWidth, i830->cpp);
+       xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d 
stride %d\n",
+                  width, height, scrn->displayWidth);
+       new_front = i830_allocate_framebuffer(scrn, i830, &mem_box, FALSE);
+       if (!new_front) {
+           scrn->virtualX = old_x;
+           scrn->virtualY = old_y;
+           scrn->displayWidth = old_width;
+           return FALSE;
+       }
+       i830_free_memory(scrn, i830->front_buffer);
+       i830->front_buffer = new_front;
+       i830_set_pixmap_bo(screen->GetScreenPixmap(screen),
+                          new_front->bo);
+       scrn->fbOffset = i830->front_buffer->offset;
+       screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen),
+                                  width, height, -1, -1, scrn->displayWidth * 
i830->cpp,
+                                  NULL);
+       xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n",
+                  i830->front_buffer->offset);
+       i830_set_new_crtc_bo(scrn);
+    }
+#endif
     return TRUE;
 }
 
@@ -1487,8 +1579,7 @@ I830PreInitCrtcConfig(ScrnInfoPtr pScrn)
     /* See i830_exa.c comments for why we limit the framebuffer size like this.
      */
     if (IS_I965G(pI830)) {
-       max_width = 8192;
-       max_height = 8192;
+       max_height = max_width = min(16384 / pI830->cpp, 8192);
     } else {
        max_width = 2048;
        max_height = 2048;
@@ -1602,7 +1693,16 @@ I830AccelMethodInit(ScrnInfoPtr pScrn)
     I830SetupOutputs(pScrn);
 
     SaveHWState(pScrn);
-    if (!xf86InitialConfiguration (pScrn, FALSE))
+    pI830->can_resize = FALSE;
+    if (pI830->accel == ACCEL_UXA && pI830->directRenderingType != DRI_XF86DRI)
+       pI830->can_resize = TRUE;
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+              "Resizable framebuffer: %s (%d %d)\n",
+              pI830->can_resize ? "available" : "not available",
+              pI830->directRenderingType, pI830->accel);
+
+    if (!xf86InitialConfiguration (pScrn, pI830->can_resize))
     {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
        RestoreHWState(pScrn);
@@ -2775,7 +2875,6 @@ failed:
            tiled ? "T" : "Unt");
     return FALSE;
 }
-
 /*
  * Try to allocate memory in several ways:
  *  1) If direct rendering is enabled, try to allocate enough memory for tiled
@@ -2790,39 +2889,9 @@ i830_memory_init(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int savedDisplayWidth = pScrn->displayWidth;
-    int i;
     Bool tiled = FALSE;
 
-    /*
-     * Adjust the display width to allow for front buffer tiling if possible
-     */
-    if (pI830->tiling) {
-       if (IS_I965G(pI830)) {
-           int tile_pixels = 512 / pI830->cpp;
-           pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) &
-               ~(tile_pixels - 1);
-           tiled = TRUE;
-       } else {
-           /* Good pitches to allow tiling.  Don't care about pitches < 1024
-            * pixels.
-            */
-           static const int pitches[] = {
-               1024,
-               2048,
-               4096,
-               8192,
-               0
-           };
-
-           for (i = 0; pitches[i] != 0; i++) {
-               if (pitches[i] >= pScrn->displayWidth) {
-                   pScrn->displayWidth = pitches[i];
-                   tiled = TRUE;
-                   break;
-               }
-           }
-       }
-    }
+    tiled = i830_tiled_width(pI830, &pScrn->displayWidth, pI830->cpp);
     /* Set up our video memory allocator for the chosen videoRam */
     if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -3043,7 +3112,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int 
argc, char **argv)
    if (!pI830->use_drm_mode)
        hwp = VGAHWPTR(pScrn);
 
-   pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
+   pScrn->displayWidth = i830_pad_drawable_width(pScrn->virtualX);
 
    /*
     * The "VideoRam" config file parameter specifies the maximum amount of
@@ -3105,7 +3174,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int 
argc, char **argv)
    /* If DRI hasn't been explicitly disabled, try to initialize it.
     * It will be used by the memory allocator.
     */
-   if (pI830->directRenderingType == DRI_NONE && I830DRIScreenInit(pScreen))
+   if (!pI830->can_resize && pI830->directRenderingType == DRI_NONE && 
I830DRIScreenInit(pScreen))
        pI830->directRenderingType = DRI_XF86DRI;
 #endif
 
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 3e3487e..ced31a8 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -758,6 +758,28 @@ i830_get_pixmap_bo(PixmapPtr pixmap)
     return NULL;
 }
 
+void
+i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pixmap->drawable.pScreen->myNum];
+    I830Ptr i830 = I830PTR(pScrn);
+    dri_bo  *old_bo = i830_get_pixmap_bo (pixmap);
+
+    if (old_bo)
+       dri_bo_unreference (old_bo);
+#if I830_USE_UXA
+    if (i830->accel == ACCEL_UXA)
+       dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, bo);
+#endif
+#ifdef XF86DRM_MODE
+    if (i830->accel == ACCEL_EXA) {
+       struct i830_exa_pixmap_priv *driver_priv =
+           exaGetPixmapDriverPrivate(pixmap);
+       if (driver_priv)
+           driver_priv->bo = bo;
+    }
+#endif
+}
 #if defined(I830_USE_UXA)
 
 static void
diff --git a/src/i830_memory.c b/src/i830_memory.c
index ca15964..132642f 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -918,10 +918,13 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char 
*name,
     mem = i830_allocate_memory(pScrn, name, aper_size, aper_align, flags);
     if (mem == NULL)
        return NULL;
+    i830_unbind_memory(pScrn, mem);
     mem->size = size;
     mem->tiling = tile_format;
     mem->pitch = pitch;
     mem->fence_nr = -1;
+    if (pScrn->vtSema || pI830->use_drm_mode)
+       i830_bind_memory(pScrn, mem);
 
 #ifdef XF86DRI
     if (mem->bo != 0) {
@@ -1145,7 +1148,7 @@ IsTileable(ScrnInfoPtr pScrn, int pitch)
  * \param pI830 I830Ptr for the screen being allocated.
  * \param FbMemBox
  */
-static i830_memory *
+i830_memory *
 i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
                          Bool secondary)
 {
@@ -1167,10 +1170,14 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr 
pI830, BoxPtr FbMemBox,
     /* We'll allocate the fb such that the root window will fit regardless of
      * rotation.
      */
-    if (!pI830->use_drm_mode && pScrn->virtualX > pScrn->virtualY)
-       fb_height = pScrn->virtualX;
-    else
-       fb_height = pScrn->virtualY;
+    fb_height = pScrn->virtualY;
+    if (!pI830->can_resize)
+    {
+       if (!pI830->use_drm_mode && pScrn->virtualX > pScrn->virtualY)
+           fb_height = pScrn->virtualX;
+       else
+           fb_height = pScrn->virtualY;
+    }
 
     FbMemBox->x1 = 0;
     FbMemBox->x2 = pScrn->displayWidth;
-- 
1.5.6.5


------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you.  Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to