[Intel-gfx] [PATCH] Reallocate frame buffer on resize
Keith Packard
keithp at keithp.com
Fri Dec 12 00:30:39 CET 2008
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;
+}
+
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
More information about the Intel-gfx
mailing list