From 5bed16099a55b401a3a91f22f5377d3da9bc0f81 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?=C5=81ukasz=20Krotowski?= Date: Wed, 19 Nov 2008 23:43:19 +0100 Subject: [PATCH] Tear-free Textured Video (Xv) acceleration. It's mostly Alex Deucher work, really. If the dest pixmap is the front buffer, stall the pipe until the vline is outside the active area. For Xv, use dst window area to determine crtc. --- src/atombios_crtc.c | 4 ++++ src/legacy_crtc.c | 19 +++++++++++++++++-- src/radeon.h | 2 ++ src/radeon_commonfuncs.c | 33 +++++++++++++++++++++++++++++++++ src/radeon_probe.h | 2 ++ src/radeon_reg.h | 8 ++++++++ src/radeon_textured_videofuncs.c | 8 ++++++++ src/radeon_video.c | 32 +++++++++++++++++++++++++++++++- src/radeon_video.h | 5 +++++ 9 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c index 4e2395f..620bc8d 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 75ab6c8..2e7063c 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 f7ae1a8..16ec6d4 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -938,8 +938,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 dba197e..5d54ee7 100644 --- a/src/radeon_commonfuncs.c +++ b/src/radeon_commonfuncs.c @@ -667,6 +667,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_RE_CRTC_VLINE | + RADEON_ENG_DISPLAY_SELECT_CRTC0)); + else + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_RE_CRTC_VLINE | + RADEON_ENG_DISPLAY_SELECT_CRTC1)); + FINISH_ACCEL(); + } +} /* MMIO: * diff --git a/src/radeon_probe.h b/src/radeon_probe.h index c14241e..7ecfdb3 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -438,6 +438,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; @@ -459,6 +460,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 19f9869..fc05efc 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) @@ -3629,6 +3632,11 @@ #define AVIVO_D1SCL_UPDATE 0x65cc # define AVIVO_D1SCL_UPDATE_LOCK (1<<16) +#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) + /* second crtc */ #define AVIVO_D2CRTC_H_TOTAL 0x6800 #define AVIVO_D2CRTC_H_BLANK_START_END 0x6804 diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c index c5ad0e1..5506c4b 100644 --- a/src/radeon_textured_videofuncs.c +++ b/src/radeon_textured_videofuncs.c @@ -1123,6 +1123,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 6249cea..423ea28 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 11b8029..a08e4e3 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -113,6 +113,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); -- 1.6.0.2