diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2008-07-16 03:14:06 -0400 |
---|---|---|
committer | Pierre Ossman <pierre@ossman.eu> | 2008-12-04 21:49:52 +0100 |
commit | 4d98acbca2e630056bf56cdcd0e23007fded2ced (patch) | |
tree | a574724160c84f68601072fb25e7507653da3ce6 | |
parent | 82d67b70d0fb747cf7b1eb0b64244ae56cb84572 (diff) |
First pass at tear-free accel
if the dest pixmap is the front buffer, stall the pipe
until the vline is outside the active area.
For EXA, pick crtc based on the larger mode area;
ideally we'd have one pixmap per crtc.
For Xv, use dst window area to determine crtc.
-rw-r--r-- | src/atombios_crtc.c | 4 | ||||
-rw-r--r-- | src/legacy_crtc.c | 19 | ||||
-rw-r--r-- | src/radeon.h | 2 | ||||
-rw-r--r-- | src/radeon_commonfuncs.c | 33 | ||||
-rw-r--r-- | src/radeon_exa.c | 27 | ||||
-rw-r--r-- | src/radeon_exa_funcs.c | 9 | ||||
-rw-r--r-- | src/radeon_exa_render.c | 6 | ||||
-rw-r--r-- | src/radeon_probe.h | 2 | ||||
-rw-r--r-- | src/radeon_reg.h | 7 | ||||
-rw-r--r-- | src/radeon_textured_videofuncs.c | 8 | ||||
-rw-r--r-- | src/radeon_video.c | 32 | ||||
-rw-r--r-- | src/radeon_video.h | 5 |
12 files changed, 150 insertions, 4 deletions
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c index 4e2395f8..620bc8dc 100644 --- a/src/atombios_crtc.c +++ b/src/atombios_crtc.c @@ -511,6 +511,10 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc, else OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); + + OUTREG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset, + ((0 << AVIVO_D1MODE_VLINE_START_SHIFT) | + (mode->VDisplay << AVIVO_D1MODE_VLINE_END_SHIFT))); } atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags); diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c index 75ab6c8a..2e7063c1 100644 --- a/src/legacy_crtc.c +++ b/src/legacy_crtc.c @@ -133,8 +133,10 @@ RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); + OUTREG(RADEON_CRTC_GUI_TRIG_VLINE, restore->crtc_gui_trig_vline); + if (IS_R300_VARIANT) - OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0); + OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0); OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); @@ -177,11 +179,13 @@ RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); + OUTREG(RADEON_CRTC2_GUI_TRIG_VLINE, restore->crtc2_gui_trig_vline); + OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid); OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid); if (IS_R300_VARIANT) - OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0); + OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0); OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); @@ -518,6 +522,8 @@ RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP); save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID); + save->crtc_gui_trig_vline = INREG(RADEON_CRTC_GUI_TRIG_VLINE); + save->crtc_offset = INREG(RADEON_CRTC_OFFSET); save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); save->crtc_pitch = INREG(RADEON_CRTC_PITCH); @@ -553,6 +559,9 @@ RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); save->crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + save->crtc2_gui_trig_vline = INREG(RADEON_CRTC2_GUI_TRIG_VLINE); + save->crtc2_offset = INREG(RADEON_CRTC2_OFFSET); save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH); @@ -946,6 +955,9 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save, (pScrn->bitsPerPixel * 8)); save->crtc_pitch |= save->crtc_pitch << 16; + save->crtc_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) | + (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT)); + if (info->IsDellServer) { save->dac2_cntl = info->SavedReg->dac2_cntl; save->tv_dac_cntl = info->SavedReg->tv_dac_cntl; @@ -1137,6 +1149,9 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save, ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); save->crtc2_pitch |= save->crtc2_pitch << 16; + save->crtc2_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) | + (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT)); + /* check to see if TV DAC is enabled for another crtc and keep it enabled */ if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON) save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; diff --git a/src/radeon.h b/src/radeon.h index 86cee4b4..826ffe38 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -941,8 +941,10 @@ extern Bool radeon_card_posted(ScrnInfoPtr pScrn); /* radeon_commonfuncs.c */ #ifdef XF86DRI extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn); +extern void RADEONWaitForVLineCP(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc); #endif extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn); +extern void RADEONWaitForVLineMMIO(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc); /* radeon_crtc.c */ extern void radeon_crtc_dpms(xf86CrtcPtr crtc, int mode); diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c index c7d42bce..556dba3f 100644 --- a/src/radeon_commonfuncs.c +++ b/src/radeon_commonfuncs.c @@ -632,6 +632,39 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) } +/* inserts a wait for vline in the command stream */ +void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + uint32_t offset; + ACCEL_PREAMBLE(); + + if ((crtc < 0) || (crtc > 1)) + return; + + if (!xf86_config->crtc[crtc]->enabled) + return; + +#ifdef USE_EXA + if (info->useEXA) + offset = exaGetPixmapOffset(pPix); + else +#endif + offset = pPix->devPrivate.ptr - info->FB; + + /* if drawing to front buffer */ + if (offset == 0) { + BEGIN_ACCEL(1); + if (crtc == 0) + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE | + RADEON_ENG_DISPLAY_SELECT_CRTC0)); + else + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE | + RADEON_ENG_DISPLAY_SELECT_CRTC1)); + FINISH_ACCEL(); + } +} /* MMIO: * diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 04c097b2..c4bc1bb1 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -192,6 +192,33 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); } +/* + * Used for vblank render stalling. + * Ideally we'd have one pixmap per crtc. + * syncing per-blit is unrealistic so, + * we sync to whichever crtc has a larger area. + */ +int RADEONBiggerCrtcArea(PixmapPtr pPix) +{ + ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int c, crtc_num = -1, area = 0; + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->enabled) + continue; + + if ((crtc->mode.HDisplay * crtc->mode.VDisplay) > area) { + area = crtc->mode.HDisplay * crtc->mode.VDisplay; + crtc_num = c; + } + } + + return crtc_num; +} + #if X_BYTE_ORDER == X_BIG_ENDIAN static unsigned long swapper_surfaces[3]; diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index 62224d01..76d6c413 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -117,6 +117,8 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); FINISH_ACCEL(); + FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix)); + return TRUE; } @@ -205,6 +207,8 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset, datatype, rop, planemask); + FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst)); + return TRUE; } @@ -264,7 +268,7 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, unsigned int hpass; uint32_t buf_pitch, dst_pitch_off; #endif -#if X_BYTE_ORDER == X_BIG_ENDIAN +#if X_BYTE_ORDER == X_BIG_ENDIAN unsigned char *RADEONMMIO = info->MMIO; unsigned int swapper = info->ModeReg->surface_cntl & ~(RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP | @@ -284,6 +288,9 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, ACCEL_PREAMBLE(); RADEON_SWITCH_TO_2D(); + + FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst)); + while ((buf = RADEONHostDataBlit(pScrn, cpp, w, dst_pitch_off, &buf_pitch, x, &y, (unsigned int*)&h, &hpass)) != 0) { diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c index a74abb63..895958cc 100644 --- a/src/radeon_exa_render.c +++ b/src/radeon_exa_render.c @@ -624,6 +624,8 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op, OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl); FINISH_ACCEL(); + FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst)); + return TRUE; } @@ -930,6 +932,8 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture, OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl); FINISH_ACCEL(); + FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst)); + return TRUE; } @@ -1877,6 +1881,8 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 4); FINISH_ACCEL(); + FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst)); + return TRUE; } diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 8c6845f7..313daa6b 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -442,6 +442,7 @@ typedef struct { uint32_t crtc_h_sync_strt_wid; uint32_t crtc_v_total_disp; uint32_t crtc_v_sync_strt_wid; + uint32_t crtc_gui_trig_vline; uint32_t crtc_offset; uint32_t crtc_offset_cntl; uint32_t crtc_pitch; @@ -463,6 +464,7 @@ typedef struct { uint32_t crtc2_h_sync_strt_wid; uint32_t crtc2_v_total_disp; uint32_t crtc2_v_sync_strt_wid; + uint32_t crtc2_gui_trig_vline; uint32_t crtc2_offset; uint32_t crtc2_offset_cntl; uint32_t crtc2_pitch; diff --git a/src/radeon_reg.h b/src/radeon_reg.h index 672d1b59..bcb83ea4 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -401,6 +401,9 @@ # define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) # define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) #define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 +# define RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT 0 +# define RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT 16 +# define RADEON_CRTC_GUI_TRIG_VLINE_INV (1 << 15) #define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 # define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) # define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3) @@ -3619,6 +3622,10 @@ #define AVIVO_D1MODE_DATA_FORMAT 0x6528 # define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) #define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652c +#define AVIVO_D1MODE_VLINE_START_END 0x6538 +# define AVIVO_D1MODE_VLINE_START_SHIFT 0 +# define AVIVO_D1MODE_VLINE_END_SHIFT 16 +# define AVIVO_D1MODE_VLINE_INV (1 << 31) #define AVIVO_D1MODE_VIEWPORT_START 0x6580 #define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c index 86532b53..edd322b3 100644 --- a/src/radeon_textured_videofuncs.c +++ b/src/radeon_textured_videofuncs.c @@ -1475,6 +1475,14 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv } } + FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap, + radeon_covering_crtc_num(pScrn, + pPriv->drw_x, + pPriv->drw_x + pPriv->dst_w, + pPriv->drw_y, + pPriv->drw_y + pPriv->dst_h, + pPriv->desired_crtc)); + while (nBox--) { int srcX, srcY, srcw, srch; int dstX, dstY, dstw, dsth; diff --git a/src/radeon_video.c b/src/radeon_video.c index 6249ceac..423ea28b 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -105,7 +105,6 @@ static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode; #define GET_PORT_PRIVATE(pScrn) \ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) -#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER static void radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) { @@ -136,6 +135,37 @@ radeon_box_area(BoxPtr box) return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); } +int +radeon_covering_crtc_num(ScrnInfoPtr pScrn, + int x1, int x2, int y1, int y2, + xf86CrtcPtr desired) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int coverage, best_coverage; + int c, best_crtc = 0; + BoxRec box, crtc_box, cover_box; + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + best_coverage = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + radeon_crtc_box(crtc, &crtc_box); + radeon_box_intersect(&cover_box, &crtc_box, &box); + coverage = radeon_box_area(&cover_box); + if (coverage && crtc == desired) { + return c; + } else if (coverage > best_coverage) { + best_crtc = c; + best_coverage = coverage; + } + } + return best_crtc; +} + +#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER static xf86CrtcPtr radeon_covering_crtc(ScrnInfoPtr pScrn, BoxPtr box, diff --git a/src/radeon_video.h b/src/radeon_video.h index 448377be..7c4151f0 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -117,6 +117,11 @@ typedef struct { int drw_x, drw_y; } RADEONPortPrivRec, *RADEONPortPrivPtr; +int +radeon_covering_crtc_num(ScrnInfoPtr pScrn, + int x1, int x2, int y1, int y2, + xf86CrtcPtr desired); + void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); |