Enable framebuffer compression (use Option "FrameBufferCompression"

"true" in your xorg.conf).  Should save ~0.5W during typical 2D usage.
This commit is contained in:
Jesse Barnes 2007-07-02 09:32:28 -07:00
parent 1e2e301348
commit b384c60897
5 changed files with 171 additions and 2 deletions

View File

@ -77,6 +77,13 @@ driver attempts to allocate space for at 3 screenfuls of pixmaps plus an
HD-sized XV video. The default used for a specific configuration can be found
by examining the __xservername__ log file.
.TP
.BI "Option \*qFrameBufferCompression\*q \*q" boolean \*q
This option controls whether the framebuffer compression feature is enabled.
If possible, the front buffer will be allocated in a tiled format and compressed
periodically to save memory bandwidth and power.
.TP
This option is only available on mobile chipsets.
.TP
.BI "Option \*qDRI\*q \*q" boolean \*q
Disable or enable DRI support.
Default: DRI is enabled for configurations where it is supported.

View File

@ -287,6 +287,8 @@ typedef struct _I830Rec {
i830_memory *front_buffer;
i830_memory *front_buffer_2;
i830_memory *compressed_front_buffer;
i830_memory *compressed_ll_buffer;
/* One big buffer for all cursors for kernels that support this */
i830_memory *cursor_mem;
/* separate small buffers for kernels that support this */
@ -342,6 +344,7 @@ typedef struct _I830Rec {
Bool allowPageFlip;
Bool TripleBuffer;
Bool disableTiling;
Bool fb_compression;
int backPitch;

View File

@ -653,15 +653,110 @@ i830_crtc_unlock (xf86CrtcPtr crtc)
#endif
}
#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
#define FBC_LL_BASE 0x03204 /* 4k page aligned */
#define FBC_CONTROL 0x03208
#define FBC_CTL_EN (1<<31)
#define FBC_CTL_PERIODIC (1<<30)
#define FBC_CTL_INTERVAL_SHIFT (16)
#define FBC_CTL_STRIDE_SHIFT (5)
#define FBC_CTL_FENCENO (1<<0)
#define FBC_COMMAND 0x0320c
#define FBC_CMD_COMPRESS (1<<0)
#define FBC_STATUS 0x03210
#define FBC_STAT_COMPRESSING (1<<31)
#define FBC_STAT_COMPRESSED (1<<30)
#define FBC_STAT_MODIFIED (1<<29)
#define FBC_STAT_CURRENT_LINE (1<<0)
#define FBC_CONTROL2 0x03214
#define FBC_CTL_CPU_FENCE (1<<1)
#define FBC_CTL_PIPEA (0<<0)
#define FBC_CTL_PIPEB (1<<0)
#define FBC_COMPRESSED_LINES (1536+32)
/*
* Several restrictions:
* - DSP[AB]CNTR - no line duplication && no pixel multiplier
* - pixel format == 15 bit, 16 bit, or 32 bit xRGB_8888
* - no alpha buffer discard
* - no dual wide display
* - progressive mode only (DSP[AB]CNTR)
*
* FIXME: verify above conditions are true
*/
static void
i830_enable_fb_compression(xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
uint32_t fbc_ctl;
unsigned long compressed_stride;
int pipe = intel_crtc->pipe;
int plane = (pipe == 0 ? FBC_CTL_PIPEA : FBC_CTL_PIPEB);
unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
unsigned long interval = 1000;
compressed_stride = pI830->compressed_front_buffer->size /
FBC_COMPRESSED_LINES;
if (uncompressed_stride < compressed_stride)
compressed_stride = uncompressed_stride;
/* FBC_CTL wants 64B units */
compressed_stride = (compressed_stride / 64) - 1;
/* Set it up... */
OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr);
OUTREG(FBC_CONTROL2, FBC_CTL_CPU_FENCE | plane);
/* enable it... */
fbc_ctl = INREG(FBC_CONTROL);
fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
OUTREG(FBC_CONTROL, fbc_ctl);
/* and request immediate compression */
OUTREG(FBC_COMMAND, FBC_CMD_COMPRESS);
}
static void
i830_disable_fb_compression(xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
uint32_t fbc_ctl;
/* Disable compression */
fbc_ctl = INREG(FBC_CONTROL);
fbc_ctl &= ~FBC_CTL_EN;
OUTREG(FBC_CONTROL, fbc_ctl);
/* Wait for compressing bit to clear */
while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
; /* nothing */
}
static void
i830_crtc_prepare (xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
crtc->funcs->dpms (crtc, DPMSModeOff);
/* Temporarily turn off FB compression during modeset */
if (pI830->fb_compression)
i830_disable_fb_compression(crtc);
}
static void
i830_crtc_commit (xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
Bool deactivate = FALSE;
@ -675,6 +770,10 @@ i830_crtc_commit (xf86CrtcPtr crtc)
xf86_reload_cursors (crtc->scrn->pScreen);
if (deactivate)
i830_pipe_a_require_deactivate (crtc->scrn);
/* Reenable FB compression if possible */
if (pI830->fb_compression)
i830_enable_fb_compression(crtc);
}
void

View File

@ -285,6 +285,7 @@ typedef enum {
OPTION_COLOR_KEY,
OPTION_CHECKDEVICES,
OPTION_MODEDEBUG,
OPTION_FBC,
#ifdef XF86DRI_MM
OPTION_INTELTEXPOOL,
OPTION_INTELMMSIZE,
@ -306,6 +307,7 @@ static OptionInfoRec I830Options[] = {
{OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE},
{OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN, {0}, FALSE},
{OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_FBC, "FrameBufferCompression", OPTV_BOOLEAN, {0}, FALSE},
#ifdef XF86DRI_MM
{OPTION_INTELTEXPOOL,"Legacy3D", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_INTELMMSIZE, "AperTexSize", OPTV_INTEGER, {0}, FALSE},
@ -2305,6 +2307,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI830->CacheLines = -1;
}
if (xf86ReturnOptValBool(pI830->Options, OPTION_FBC, FALSE))
pI830->fb_compression = TRUE;
else
pI830->fb_compression = FALSE;
pI830->disableTiling = FALSE;
if (I830IsPrimary(pScrn)) {

View File

@ -902,8 +902,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
name = secondary ? "secondary front buffer" : "front buffer";
/* Attempt to allocate it tiled first if we have page flipping on. */
if (!pI830->disableTiling && pI830->allowPageFlip &&
IsTileable(pScrn, pitch))
if ((!pI830->disableTiling && pI830->allowPageFlip &&
IsTileable(pScrn, pitch)) || pI830->fb_compression)
{
/* XXX: probably not the case on 965 */
if (IS_I9XX(pI830))
@ -1022,6 +1022,56 @@ i830_allocate_cursor_buffers(ScrnInfoPtr pScrn)
return TRUE;
}
static void i830_setup_fb_compression(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
/* Only mobile chips since 845 support this feature */
if (!IS_MOBILE(pI830)) {
pI830->fb_compression = FALSE;
goto out;
}
/*
* Compressed framebuffer limitations:
* - contiguous, physical, uncached memory
* - ideally as large as the front buffer(s), smaller sizes cache less
* - uncompressed buffer must be tiled w/pitch 2k-16k
* - uncompressed fb is <= 2048 in width, 0 mod 8
* - uncompressed fb is <= 1536 in height, 0 mod 2
* - compressed fb stride is <= uncompressed stride
* - SR display watermarks must be equal between 16bpp and 32bpp?
* - both compressed and line buffers must be in stolen memory
*/
pI830->compressed_front_buffer =
i830_allocate_memory(pScrn, "compressed frame buffer",
MB(6), KB(4),
NEED_PHYSICAL_ADDR);
if (!pI830->compressed_front_buffer) {
pI830->fb_compression = FALSE;
goto out;
}
pI830->compressed_ll_buffer =
i830_allocate_memory(pScrn, "compressed ll buffer",
1568, KB(4), NEED_PHYSICAL_ADDR);
if (!pI830->compressed_ll_buffer) {
i830_free_memory(pScrn, pI830->compressed_front_buffer);
pI830->fb_compression = FALSE;
goto out;
}
out:
if (pI830->fb_compression)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression "
"enabled\n");
else
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Allocation error, framebuffer"
" compression disabled\n");
return;
}
/*
* Allocate memory for 2D operation. This includes the (front) framebuffer,
* ring buffer, scratch memory, HW cursor.
@ -1046,6 +1096,9 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
/* Allocate the ring buffer first, so it ends up in stolen mem. */
i830_allocate_ringbuffer(pScrn);
if (pI830->fb_compression)
i830_setup_fb_compression(pScrn);
/* Next, allocate other fixed-size allocations we have. */
if (!pI830->SWCursor && !i830_allocate_cursor_buffers(pScrn)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,