diff options
author | Keith Packard <keithp@keithp.com> | 2008-12-15 15:35:35 -0800 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2009-01-06 09:31:39 -0800 |
commit | 8237faf8f3ca73ecdf0ef009a7d361b318726f6f (patch) | |
tree | 3331e4118b7ef6cc10247a2baf6fa8837b692cf8 /src | |
parent | 21bd4e8974e4c0e83f5f95adb0fc17290444caf5 (diff) |
Resize framebuffer on screen size change (requires UXA and DRI2)
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/i830.h | 9 | ||||
-rw-r--r-- | src/i830_display.c | 31 | ||||
-rw-r--r-- | src/i830_display.h | 1 | ||||
-rw-r--r-- | src/i830_driver.c | 149 | ||||
-rw-r--r-- | src/i830_exa.c | 27 | ||||
-rw-r--r-- | src/i830_memory.c | 120 |
6 files changed, 184 insertions, 153 deletions
@@ -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 @@ -267,6 +268,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]; @@ -468,6 +471,8 @@ typedef struct _I830Rec { int drmMinor; Bool allocate_classic_textures; + Bool can_resize; + Bool want_vblank_interrupts; #ifdef DAMAGE DamagePtr pDamage; @@ -907,6 +912,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 4e4ff340..50fbc4d8 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -387,12 +387,14 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; - unsigned long Start, Offset; + unsigned long Start, Offset, Stride; int dspbase = (plane == 0 ? DSPABASE : DSPBBASE); int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF); int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); + int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; Offset = ((y * pScrn->displayWidth + x) * pI830->cpp); + Stride = pScrn->displayWidth * pI830->cpp; if (pI830->front_buffer == NULL) { /* During startup we may be called as part of monitor detection while * there is no memory allocation done, so just supply a dummy base @@ -403,6 +405,7 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) /* offset is done by shadow painting code, not here */ Start = (char *)crtc->rotatedData - (char *)pI830->FbBase; Offset = 0; + Stride = intel_crtc->rotate_mem->pitch; } else if (I830IsPrimary(pScrn)) { Start = pI830->front_buffer->offset; } else { @@ -410,6 +413,10 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) Start = pI8301->front_buffer_2->offset; } + crtc->x = x; + crtc->y = y; + + OUTREG(dspstride, Stride); if (IS_I965G(pI830)) { OUTREG(dspbase, Offset); POSTING_READ(dspbase); @@ -1199,7 +1206,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; - int dspstride_reg = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS; int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE; int i, num_outputs = 0; @@ -1494,7 +1500,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, ((adjusted_mode->CrtcVBlankEnd - 1) << 16)); OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) | ((adjusted_mode->CrtcVSyncEnd - 1) << 16)); - OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp); /* pipesrc and dspsize control the size that is scaled from, which should * always be the user's requested size. */ @@ -1640,10 +1645,28 @@ 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) +{ + 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 && !crtc->transform_in_use) + i830PipeSetBase(crtc, crtc->x, crtc->y); + } +} + void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) { diff --git a/src/i830_display.h b/src/i830_display.h index 1eeb7f15..8d767b10 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 27d86948..3e27b07d 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1085,11 +1085,108 @@ I830IsPrimary(ScrnInfoPtr pScrn) return TRUE; } + +/* + * Adjust *width to allow for tiling if possible + */ +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 + */ +int +i830_pad_drawable_width(int width, int cpp) +{ + 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, *old_front; + BoxRec mem_box; + Bool tiled; + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; + + scrn->displayWidth = i830_pad_drawable_width(width, i830->cpp); + 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); + I830Sync(scrn); + i830WaitForVblank(scrn); + 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; + } + old_front = 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); + I830Sync(scrn); + i830WaitForVblank(scrn); + i830_free_memory(scrn, old_front); + } +#endif return TRUE; } @@ -1487,8 +1584,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; @@ -1595,7 +1691,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); @@ -2729,7 +2834,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 @@ -2744,39 +2848,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, @@ -2997,7 +3071,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, pI830->cpp); /* * The "VideoRam" config file parameter specifies the maximum amount of @@ -3061,8 +3135,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) */ if (pI830->directRenderingType == DRI_NONE && pI830->SWCursor) pI830->directRenderingType = DRI_DISABLED; - - if (pI830->directRenderingType == DRI_NONE && I830DRIScreenInit(pScreen)) + if (!pI830->can_resize && pI830->directRenderingType == DRI_NONE && I830DRIScreenInit(pScreen)) pI830->directRenderingType = DRI_XF86DRI; if (pI830->directRenderingType == DRI_XF86DRI) { diff --git a/src/i830_exa.c b/src/i830_exa.c index aeffedd8..b300fdc0 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -758,6 +758,32 @@ 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) { + dri_bo_reference(bo); + 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) { + dri_bo_reference(bo); + driver_priv->bo = bo; + } + } +#endif +} #if defined(I830_USE_UXA) static void @@ -893,6 +919,7 @@ void i830_uxa_create_screen_resources(ScreenPtr pScreen) if (bo != NULL) { PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); i830_uxa_set_pixmap_bo (pixmap, bo); + dri_bo_reference(bo); } } diff --git a/src/i830_memory.c b/src/i830_memory.c index 2dee0bf1..b6d80263 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1130,7 +1130,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) { @@ -1152,10 +1152,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; @@ -2115,114 +2119,8 @@ Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name, } #endif -#if 0 -static i830_memory * -i830_allocate_framebuffer_new(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox) -{ - unsigned int pitch = pScrn->displayWidth * pI830->cpp; - unsigned long minspace, avail; - int cacheLines; - int align; - long size, fb_height; - char *name; - int flags; - i830_memory *front_buffer = NULL; - Bool tiling; - - flags = ALLOW_SHARING; - - /* Clear everything first. */ - memset(FbMemBox, 0, sizeof(*FbMemBox)); - - 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. - */ - minspace = pitch * pScrn->virtualY; - avail = pScrn->videoRam * 1024; - cacheLines = 0; - - size = pitch * (fb_height + cacheLines); - size = ROUND_TO_PAGE(size); - - name = "front buffer"; - - /* Front buffer tiling has to be disabled with G965 XAA because some of the - * acceleration operations (non-XY COLOR_BLT) can't be done to tiled - * buffers. - */ - if (!(pI830->accel == ACCEL_EXA) && IS_I965G(pI830)) - tiling = FALSE; - else - tiling = pI830->tiling; - - if (pI830->use_drm_mode) - tiling = FALSE; - - /* Attempt to allocate it tiled first if we have page flipping on. */ - if (tiling && IsTileable(pScrn, pitch)) { - /* XXX: probably not the case on 965 */ - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - front_buffer = i830_allocate_memory_tiled(pScrn, name, size, - pitch, align, flags, - TILE_XMAJOR); - } - - /* If not, attempt it linear */ - if (front_buffer == NULL) { - front_buffer = i830_allocate_memory(pScrn, name, size, KB(64), flags); - } - - if (front_buffer == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "framebuffer. Is your VideoRAM set too low?\n"); - - return NULL; - } - - return front_buffer; -} -#endif uint32_t i830_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch) { return 0; - -#if 0 - I830Ptr pI830 = I830PTR(pScrn); - i830_memory *old_buffer; - - pScrn->virtualX = width; - pScrn->virtualY = height; - pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; - - *pitch = pScrn->displayWidth * pI830->cpp; - - old_buffer = pI830->front_buffer; - - pI830->front_buffer = - i830_allocate_framebuffer_new(pScrn, pI830, &pI830->FbMemBox); - - ErrorF("old front size %08lx, new front size %08lx\n", - old_buffer->bo->size, pI830->front_buffer->bo->size); - ErrorF("old front offset %08lx, new front offset %08lx\n", - old_buffer->bo->offset, pI830->front_buffer->bo->offset); - - i830_free_memory(pScrn, old_buffer); - - i830_update_front_offset(pScrn); - - return pI830->front_buffer->bo->handle; -#endif } |