[Intel-gfx] [PATCH] Reallocate frame buffer on resize

Eric Anholt eric at anholt.net
Fri Dec 12 03:15:06 CET 2008


On Thu, 2008-12-11 at 15:30 -0800, Keith Packard wrote:
> When running UXA (and not DRI1), we can resize the frame buffer.
> Signed-off-by: Keith Packard <keithp at 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;
> +}
> +

I know of a 64b alignment required for display planes, but I'm not sure
what a 64-pixel alignment is about.  Also, #define ALIGN() should be in
a header already, seriously.

>  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;
-- 
Eric Anholt
eric at anholt.net                         eric.anholt at intel.com


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20081211/f86c45d2/attachment.sig>


More information about the Intel-gfx mailing list