diff options
author | Jesse Barnes <jesse.barnes@intel.com> | 2007-08-03 20:40:45 -0700 |
---|---|---|
committer | Jesse Barnes <jesse.barnes@intel.com> | 2007-08-03 20:40:45 -0700 |
commit | 3d3c0e8c55f639a501c0756948b518abd903d7d0 (patch) | |
tree | d43002abbaf2829e2a6a979f17b32ef2f13760eb | |
parent | 0da4f2b0cd7203377ad10407928a367b8c6d310e (diff) |
Tiled rendering & fbc fixes:
- actually enable tiling in DSP(A|B)CNTR if needed
- add logic to EXA routines for tiled case (still needs work)
- enable/disable fbc on DPMS events (meant moving functions higher in file)
- fix fence register pitch programming (use correct pitch instead of kludged value)
-rw-r--r-- | src/i810_reg.h | 4 | ||||
-rw-r--r-- | src/i830.h | 1 | ||||
-rw-r--r-- | src/i830_display.c | 234 | ||||
-rw-r--r-- | src/i830_exa.c | 54 | ||||
-rw-r--r-- | src/i830_memory.c | 5 | ||||
-rw-r--r-- | src/i830_reg.h | 7 |
6 files changed, 186 insertions, 119 deletions
diff --git a/src/i810_reg.h b/src/i810_reg.h index d1fed22c..03e10d64 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -2029,6 +2029,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DSPBCNTR 0x71180 #define DISPLAY_PLANE_ENABLE (1<<31) #define DISPLAY_PLANE_DISABLE 0 +#define DISPLAY_PLANE_TILED (1<<10) #define DISPPLANE_GAMMA_ENABLE (1<<30) #define DISPPLANE_GAMMA_DISABLE 0 #define DISPPLANE_PIXFORMAT_MASK (0xf<<26) @@ -2168,12 +2169,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|(0x4)) #define XY_COLOR_BLT_WRITE_ALPHA (1<<21) #define XY_COLOR_BLT_WRITE_RGB (1<<20) +#define XY_COLOR_BLT_TILED (1<<11) #define XY_SETUP_CLIP_BLT_CMD ((2<<29)|(3<<22)|1) #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define XY_SRC_COPY_BLT_SRC_TILED (1<<15) +#define XY_SRC_COPY_BLT_DST_TILED (1<<11) #define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|0x4) #define SRC_COPY_BLT_WRITE_ALPHA (1<<21) @@ -407,6 +407,7 @@ typedef struct _I830Rec { #ifdef I830_USE_EXA unsigned int copy_src_pitch; unsigned int copy_src_off; + unsigned int copy_src_tiled; ExaDriverPtr EXADriverPtr; #endif diff --git a/src/i830_display.c b/src/i830_display.c index 26873fef..6fe7be74 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -498,6 +498,123 @@ i830_pipe_a_require_deactivate (ScrnInfoPtr scrn) return; } +static Bool +i830_use_fb_compression(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB); + + if (!pI830->fb_compression) + return FALSE; + + /* Pre-965 only supports plane A */ + if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA) + return FALSE; + + /* Need 15, 16, or 32 (w/alpha) pixel format */ + if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */ + pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */ + return FALSE; + + /* + * No checks for pixel multiply, incl. horizontal, or interlaced modes + * since they're currently unused. + */ + return TRUE; +} + +/* + * 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) + * - uncompressed fb is <= 2048 in width, 0 mod 8 + * - uncompressed fb is <= 1536 in height, 0 mod 2 + * - SR display watermarks must be equal between 16bpp and 32bpp? + * + * 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 = 0; + unsigned long compressed_stride; + int pipe = intel_crtc->pipe; + /* FIXME: plane & pipe might not always be equal */ + int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB); + unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp; + unsigned long interval = 1000; + + if (INREG(FBC_CONTROL) & FBC_CTL_EN) { + char cur_pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a'; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fbc already enabled on " + "pipe %c, not enabling on pipe %c\n", cur_pipe, pipe ? 'b' : + 'a'); + return; + } + + compressed_stride = pI830->compressed_front_buffer->size / + FBC_LL_SIZE; + + if (uncompressed_stride < compressed_stride) + compressed_stride = uncompressed_stride; + + /* FBC_CTL wants 64B units */ + compressed_stride = (compressed_stride / 64) - 1; + + /* Set it up... */ + /* Wait for compressing bit to clear */ + while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING) + ; /* nothing */ + i830WaitForVblank(pScrn); + OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr); + OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr + 6); + OUTREG(FBC_CONTROL2, FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_FULL | + FBC_CTL_CPU_FENCE | plane); + + /* Zero buffers */ + memset(pI830->FbBase + pI830->compressed_front_buffer->offset, 0, + pI830->compressed_front_buffer->size); + memset(pI830->FbBase + pI830->compressed_ll_buffer->offset, 0, + pI830->compressed_ll_buffer->size); + + /* enable it... */ + 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; + fbc_ctl |= FBC_CTL_UNCOMPRESSIBLE; + OUTREG(FBC_CONTROL, fbc_ctl); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on plane %c\n", pipe ? + 'b' : 'a'); +} + +static void +i830_disable_fb_compression(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + uint32_t fbc_ctl; + char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a'; + + /* 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 */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on pipe %c\n", pipe); +} /** * Sets the power management mode of the pipe and plane. @@ -561,8 +678,16 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Give the overlay scaler a chance to enable if it's on this pipe */ i830_crtc_dpms_video(crtc, TRUE); + + /* Reenable compression if needed */ + if (i830_use_fb_compression(crtc)) + i830_enable_fb_compression(crtc); break; case DPMSModeOff: + /* Shut off compression if in use */ + if (i830_use_fb_compression(crtc)) + i830_disable_fb_compression(crtc); + /* Give the overlay scaler a chance to disable if it's on this pipe */ i830_crtc_dpms_video(crtc, FALSE); @@ -656,112 +781,6 @@ i830_crtc_unlock (xf86CrtcPtr crtc) #endif } -static Bool -i830_use_fb_compression(xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); - I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - int pipe = intel_crtc->pipe; - int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB); - - if (!pI830->fb_compression) - return FALSE; - - /* Pre-965 only supports plane A */ - if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA) - return FALSE; - - /* Need 15, 16, or 32 (w/alpha) pixel format */ - if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */ - pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */ - return FALSE; - - /* - * No checks for pixel multiply, incl. horizontal, or interlaced modes - * since they're currently unused. - */ - return TRUE; -} - -/* - * 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) - * - uncompressed fb is <= 2048 in width, 0 mod 8 - * - uncompressed fb is <= 1536 in height, 0 mod 2 - * - SR display watermarks must be equal between 16bpp and 32bpp? - * - * 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_PLANEA : FBC_CTL_PLANEB); - unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp; - unsigned long interval = 1000; - - if (INREG(FBC_CONTROL) & FBC_CTL_EN) { - char cur_pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a'; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fbc already enabled on " - "pipe %c, not enabling on pipe %c\n", cur_pipe, pipe ? 'b' : - 'a'); - return; - } - - compressed_stride = pI830->compressed_front_buffer->size / - FBC_LL_SIZE; - - 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 + FBC_LL_PAD); - 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); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on pipe %c\n", pipe ? - 'b' : 'a'); -} - -static void -i830_disable_fb_compression(xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); - uint32_t fbc_ctl; - char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a'; - - /* 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 */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on pipe %c\n", pipe); -} - static void i830_crtc_prepare (xf86CrtcPtr crtc) { @@ -1059,6 +1078,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, else dspcntr |= DISPPLANE_SEL_PIPE_B; + if (pI830->tiling) + dspcntr |= DISPLAY_PLANE_TILED; + pipeconf = INREG(pipeconf_reg); if (pipe == 0 && !IS_I965G(pI830)) { diff --git a/src/i830_exa.c b/src/i830_exa.c index fed4067b..5da153e0 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -97,6 +97,16 @@ const int I830PatternROP[16] = ROP_1 }; +static Bool +exaPixmapInFrontbuffer(PixmapPtr p) +{ + ScreenPtr pScreen = p->drawable.pScreen; + + if (p == pScreen->GetScreenPixmap(pScreen)) + return TRUE; + return FALSE; +} + /** * I830EXASync - wait for a command to finish * @pScreen: current screen @@ -162,16 +172,26 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); unsigned long offset; + uint32_t cmd; offset = exaGetPixmapOffset(pPixmap); { BEGIN_LP_RING(6); + + cmd = XY_COLOR_BLT_CMD; + if (pPixmap->drawable.bitsPerPixel == 32) - OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA - | XY_COLOR_BLT_WRITE_RGB); - else - OUT_RING(XY_COLOR_BLT_CMD); + cmd |= XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; + + if (pI830->tiling && exaPixmapInFrontbuffer(pPixmap)) { + /* Fixup pitch for destination if tiled */ + pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | + (pI830->BR[13] & 0xffff0000); + cmd |= XY_COLOR_BLT_TILED; + } + + OUT_RING(cmd); OUT_RING(pI830->BR[13]); OUT_RING((y1 << 16) | (x1 & 0xffff)); @@ -208,6 +228,8 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap); pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap); + pI830->copy_src_tiled = (pI830->tiling && + exaPixmapInFrontbuffer(pSrcPixmap)); pI830->BR[13] = exaGetPixmapPitch(pDstPixmap); pI830->BR[13] |= I830CopyROP[alu] << 16; @@ -231,6 +253,7 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1, { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); + uint32_t cmd; int dst_x2, dst_y2; unsigned int dst_off; @@ -242,11 +265,26 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1, { BEGIN_LP_RING(8); + cmd = XY_SRC_COPY_BLT_CMD; + if (pDstPixmap->drawable.bitsPerPixel == 32) - OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - else - OUT_RING(XY_SRC_COPY_BLT_CMD); + cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB; + + if (pI830->tiling && exaPixmapInFrontbuffer(pDstPixmap)) { + /* Fixup pitch for destination if tiled */ + pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | + (pI830->BR[13] & 0xffff0000); + cmd |= XY_SRC_COPY_BLT_DST_TILED; + } + + if (pI830->copy_src_tiled) { + pI830->copy_src_pitch = + (ROUND_TO(pI830->copy_src_pitch & 0xffff, 512) >> 2) | + (pI830->copy_src_pitch & 0xffff0000); + cmd |= XY_SRC_COPY_BLT_SRC_TILED; + } + + OUT_RING(cmd); OUT_RING(pI830->BR[13]); OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff)); diff --git a/src/i830_memory.c b/src/i830_memory.c index b38a5dfe..ccd26b39 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1453,11 +1453,6 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset, assert(tile_format != TILING_NONE); if (IS_I965G(pI830)) { - if (tile_format == TILING_XMAJOR) - pitch = 512; - else - pitch = 128; - if (nr < 0 || nr >= FENCE_NEW_NR) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "i830_set_fence(): fence %d out of range\n",nr); diff --git a/src/i830_reg.h b/src/i830_reg.h index 8a2a98ac..df22ed41 100644 --- a/src/i830_reg.h +++ b/src/i830_reg.h @@ -36,6 +36,7 @@ #define FBC_CTL_EN (1<<31) #define FBC_CTL_PERIODIC (1<<30) #define FBC_CTL_INTERVAL_SHIFT (16) +#define FBC_CTL_UNCOMPRESSIBLE (1<<14) #define FBC_CTL_STRIDE_SHIFT (5) #define FBC_CTL_FENCENO (1<<0) #define FBC_COMMAND 0x0320c @@ -46,9 +47,15 @@ #define FBC_STAT_MODIFIED (1<<29) #define FBC_STAT_CURRENT_LINE (1<<0) #define FBC_CONTROL2 0x03214 +#define FBC_CTL_FENCE_DBL (0<<4) +#define FBC_CTL_IDLE_IMM (0<<2) +#define FBC_CTL_IDLE_FULL (1<<2) +#define FBC_CTL_IDLE_LINE (2<<2) +#define FBC_CTL_IDLE_DEBUG (3<<2) #define FBC_CTL_CPU_FENCE (1<<1) #define FBC_CTL_PLANEA (0<<0) #define FBC_CTL_PLANEB (1<<0) +#define FBC_FENCE_OFF 0x0321b #define FBC_LL_SIZE (1536) #define FBC_LL_PAD (32) |