diff options
author | Michel Dänzer <michel@tungstengraphics.com> | 2006-09-30 19:25:20 +0200 |
---|---|---|
committer | Michel Dänzer <michel@tungstengraphics.com> | 2006-09-30 19:25:20 +0200 |
commit | d43ad88fa3913437f6987ab5ab46a38f0cb555a8 (patch) | |
tree | ecf6c5c7334fc3a7fd16a8fd65bd24a2c6d582bb /src | |
parent | 146ea328b7962f56c6ab47fbe2adc7561b36189c (diff) |
radeon: Add support for page flipping with EXA.
Also use the damage layer directly instead of via shadowfb and blit dirty
rectangles to the second page in LeaveServer in order to try and improve the
tradeoff between performance and correctness.
Diffstat (limited to 'src')
-rw-r--r-- | src/radeon.h | 18 | ||||
-rw-r--r-- | src/radeon_dri.c | 170 | ||||
-rw-r--r-- | src/radeon_driver.c | 50 | ||||
-rw-r--r-- | src/radeon_exa.c | 4 | ||||
-rw-r--r-- | src/radeon_exa_funcs.c | 53 |
5 files changed, 169 insertions, 126 deletions
diff --git a/src/radeon.h b/src/radeon.h index 73b3538..8068cd9 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -71,6 +71,10 @@ #include "radeon_dripriv.h" #include "dri.h" #include "GL/glxint.h" +#ifdef DAMAGE +#include "damage.h" +#include "globals.h" +#endif #endif /* Render support */ @@ -599,6 +603,9 @@ typedef struct { Bool depthMoves; /* Enable depth moves -- slow! */ Bool allowPageFlip; /* Enable 3d page flipping */ +#ifdef DAMAGE + DamagePtr pDamage; +#endif Bool have3DWindows; /* Are there any 3d clients? */ drmSize gartSize; @@ -847,7 +854,17 @@ extern Bool RADEONAccelInit(ScreenPtr pScreen); extern Bool RADEONSetupMemEXA (ScreenPtr pScreen); extern Bool RADEONDrawInitMMIO(ScreenPtr pScreen); #ifdef XF86DRI +extern Bool RADEONGetDatatypeBpp(int bpp, CARD32 *type); +extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, + CARD32 *pitch_offset); extern Bool RADEONDrawInitCP(ScreenPtr pScreen); +extern void RADEONDoPrepareCopyCP(ScrnInfoPtr pScrn, + CARD32 src_pitch_offset, + CARD32 dst_pitch_offset, + CARD32 datatype, int rop, + Pixel planemask); +extern void RADEONCopyCP(PixmapPtr pDst, int srcX, int srcY, int dstX, + int dstY, int w, int h); #endif #endif #ifdef USE_XAA @@ -898,7 +915,6 @@ extern void RADEONDRICloseScreen(ScreenPtr pScreen); extern void RADEONDRIResume(ScreenPtr pScreen); extern Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen); extern void RADEONDRIAllocatePCIGARTTable(ScreenPtr pScreen); -extern void RADEONDRIInitPageFlip(ScreenPtr pScreen); extern void RADEONDRIStop(ScreenPtr pScreen); extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn); diff --git a/src/radeon_dri.c b/src/radeon_dri.c index ca70e56..c50ebcb 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -54,8 +54,6 @@ #include "xf86PciInfo.h" #include "windowstr.h" - -#include "shadowfb.h" /* GLX/DRI/DRM definitions */ #define _XF86DRI_SERVER_ #include "GL/glxtokens.h" @@ -70,7 +68,7 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen); static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen); static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen); -#ifdef USE_XAA +#ifdef DAMAGE static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); #endif @@ -420,6 +418,19 @@ static void RADEONLeaveServer(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); RING_LOCALS; +#ifdef DAMAGE + if (info->pDamage) { + RegionPtr pDamageReg = DamageRegion(info->pDamage); + + if (pDamageReg) { + RADEONDRIRefreshArea(pScrn, REGION_NUM_RECTS(pDamageReg), + REGION_RECTS(pDamageReg)); + + DamageEmpty(info->pDamage); + } + } +#endif + /* The CP is always running, but if we've generated any CP commands * we must flush them to the kernel module now. */ @@ -1624,30 +1635,6 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) return TRUE; } -void RADEONDRIInitPageFlip(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); - -#ifdef USE_XAA - /* Have shadowfb run only while there is 3d active. This must happen late, - * after XAAInit has been called - */ - if (!info->useEXA) { - if (!ShadowFBInit( pScreen, RADEONDRIRefreshArea )) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "ShadowFB init failed, Page Flipping disabled\n"); - info->allowPageFlip = 0; - } else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "ShadowFB initialized for Page Flipping\n"); - } else -#endif /* USE_XAA */ - { - info->allowPageFlip = 0; - } -} - /** * This function will attempt to get the Radeon hardware back into shape * after a resume from disc. @@ -1798,8 +1785,6 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) } } -#ifdef USE_XAA - /* Use callbacks from dri.c to support pageflipping mode for a single * 3d context without need for any specific full-screen extension. * @@ -1808,12 +1793,12 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) */ -/* Use the shadowfb module to maintain a list of dirty rectangles. +#ifdef DAMAGE + +/* Use the damage layer to maintain a list of dirty rectangles. * These are blitted to the back buffer to keep both buffers clean * during page-flipping when the 3d application isn't fullscreen. * - * Unlike most use of the shadowfb code, both buffers are in video memory. - * * An alternative to this would be to organize for all on-screen drawing * operations to be duplicated for the two buffers. That might be * faster, but seems like a lot more work... @@ -1824,7 +1809,11 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) { RADEONInfoPtr info = RADEONPTR(pScrn); int i; - RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + ScreenPtr pScreen = pScrn->pScreen; + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); +#ifdef USE_EXA + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); +#endif if (!info->directRenderingInited) return; @@ -1835,64 +1824,98 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) return; - /* XXX: implement for EXA */ /* pretty much a hack. */ - /* Make sure accel has been properly inited */ - if (info->accel == NULL || info->accel->SetupForScreenToScreenCopy == NULL) - return; - if (info->tilingEnabled) - info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; - (*info->accel->SetupForScreenToScreenCopy)(pScrn, - 1, 1, GXcopy, - (CARD32)(-1), -1); +#ifdef USE_EXA + if (info->useEXA) { + CARD32 src_pitch_offset, dst_pitch_offset, datatype; + + RADEONGetPixmapOffsetPitch(pPix, &src_pitch_offset); + dst_pitch_offset = src_pitch_offset + (info->backOffset >> 10); + RADEONGetDatatypeBpp(pScrn->bitsPerPixel, &datatype); + info->xdir = info->ydir = 1; + + RADEONDoPrepareCopyCP(pScrn, src_pitch_offset, dst_pitch_offset, datatype, + GXcopy, ~0); + } +#endif + +#ifdef USE_XAA + if (!info->useEXA) { + /* Make sure accel has been properly inited */ + if (info->accel == NULL || info->accel->SetupForScreenToScreenCopy == NULL) + return; + if (info->tilingEnabled) + info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; + (*info->accel->SetupForScreenToScreenCopy)(pScrn, + 1, 1, GXcopy, + (CARD32)(-1), -1); + } +#endif for (i = 0 ; i < num ; i++, pbox++) { int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1); int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1); if (xa <= xb && ya <= yb) { - (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, - xa + info->backX, - ya + info->backY, - xb - xa + 1, - yb - ya + 1); +#ifdef USE_EXA + if (info->useEXA) { + RADEONCopyCP(pPix, xa, ya, xa, ya, xb - xa + 1, yb - ya + 1); + } +#endif + +#ifdef USE_XAA + if (!info->useEXA) { + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, + xa + info->backX, + ya + info->backY, + xb - xa + 1, + yb - ya + 1); + } +#endif } } + +#ifdef USE_XAA info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; +#endif } -#endif /* USE_XAA */ +#endif /* DAMAGE */ static void RADEONEnablePageFlip(ScreenPtr pScreen) { -#ifdef USE_XAA +#ifdef DAMAGE ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); - /* XXX: Fix in EXA case */ if (info->allowPageFlip) { - /* pretty much a hack. */ - if (info->tilingEnabled) - info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; - /* Duplicate the frontbuffer to the backbuffer */ - (*info->accel->SetupForScreenToScreenCopy)(pScrn, - 1, 1, GXcopy, - (CARD32)(-1), -1); + BoxRec box = { .x1 = 0, .y1 = 0, .x2 = pScrn->virtualX - 1, + .y2 = pScrn->virtualY - 1 }; + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + if (!info->pDamage) { + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); + + /* Have damage run only while there is 3d active. + */ + info->pDamage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, + pScreen, pPix); + + if (info->pDamage == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No screen damage record, page flipping disabled\n"); + info->allowPageFlip = 0; + return; + } + + DamageRegister(&pPix->drawable, info->pDamage); + } - (*info->accel->SubsequentScreenToScreenCopy)(pScrn, - 0, - 0, - info->backX, - info->backY, - pScrn->virtualX, - pScrn->virtualY); - - info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; pSAREAPriv->pfAllowPageFlip = 1; + RADEONDRIRefreshArea(pScrn, 1, &box); } -#endif /* USE_XAA */ +#endif } static void RADEONDisablePageFlip(ScreenPtr pScreen) @@ -1902,6 +1925,17 @@ static void RADEONDisablePageFlip(ScreenPtr pScreen) * -- DRM needs to cope with Front-to-Back swapbuffers. */ RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); +#ifdef DAMAGE + RADEONInfoPtr info = RADEONPTR(xf86Screens[pScreen->myNum]); + + if (info->pDamage) { + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); + + DamageUnregister(&pPix->drawable, info->pDamage); + DamageDestroy(info->pDamage); + info->pDamage = NULL; + } +#endif pSAREAPriv->pfAllowPageFlip = 0; } diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 60725da..bb1e070 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -55,7 +55,7 @@ * This server does not yet support these XFree86 4.0 features: * !!!! FIXME !!!! * DDC1 & DDC2 - * shadowfb (Note: dri uses shadowfb for another purpose in radeon_dri.c) + * shadowfb * overlay planes * * Modified by Marc Aurele La France (tsi@xfree86.org) for ATI driver merge. @@ -360,11 +360,6 @@ static const char *driSymbols[] = { "DRICreatePCIBusID", NULL }; - -static const char *driShadowFBSymbols[] = { - "ShadowFBInit", - NULL -}; #endif static const char *vbeSymbols[] = { @@ -411,7 +406,6 @@ void RADEONLoaderRefSymLists(void) #ifdef XF86DRI drmSymbols, driSymbols, - driShadowFBSymbols, #endif fbdevHWSymbols, vbeSymbols, @@ -3214,6 +3208,7 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); MessageType from; + char *reason; info->directRenderingEnabled = FALSE; info->directRenderingInited = FALSE; @@ -3389,30 +3384,25 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) OPTION_NO_BACKBUFFER, FALSE); -#ifdef XF86DRI + info->allowPageFlip = 0; + +#ifdef DAMAGE if (info->noBackBuffer) { - info->allowPageFlip = 0; - } else if (!xf86LoadSubModule(pScrn, "shadowfb")) { - info->allowPageFlip = 0; - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't load shadowfb module:\n"); + from = X_DEFAULT; + reason = " because back buffer disabled"; } else { - xf86LoaderReqSymLists(driShadowFBSymbols, NULL); - - info->allowPageFlip = xf86ReturnOptValBool(info->Options, - OPTION_PAGE_FLIP, - FALSE); - if (info->allowPageFlip && info->useEXA) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Page flipping not allowed with EXA, disabling.\n"); - info->allowPageFlip = FALSE; - } + from = xf86GetOptValBool(info->Options, OPTION_PAGE_FLIP, + &info->allowPageFlip) ? X_CONFIG : X_DEFAULT; + reason = ""; } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", - info->allowPageFlip ? "en" : "dis"); +#else + from = X_DEFAULT; + reason = " because Damage layer not available at build time"; #endif + xf86DrvMsg(pScrn->scrnIndex, from, "Page Flipping %sabled%s\n", + info->allowPageFlip ? "en" : "dis", reason); + info->DMAForXv = TRUE; from = xf86GetOptValBool(info->Options, OPTION_XV_DMA, &info->DMAForXv) ? X_CONFIG : X_INFO; @@ -4835,14 +4825,6 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->accelOn = FALSE; } -#ifdef XF86DRI - /* Init page flipping if enabled now */ - if (info->allowPageFlip) { - RADEONTRACE(("Initializing Page Flipping\n")); - RADEONDRIInitPageFlip(pScreen); - } -#endif - /* Init DPMS */ RADEONTRACE(("Initializing DPMS\n")); xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0); diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 9ef74e9..7e57fe7 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -118,7 +118,7 @@ static __inline__ CARD32 F_TO_DW(float val) /* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we * require src and dest datatypes to be equal. */ -static Bool RADEONGetDatatypeBpp(int bpp, CARD32 *type) +Bool RADEONGetDatatypeBpp(int bpp, CARD32 *type) { switch (bpp) { case 8: @@ -172,7 +172,7 @@ static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, CARD32 *pitch_offset, return TRUE; } -static Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset) +Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset) { RINFO_FROM_SCREEN(pPix->drawable.pScreen); CARD32 pitch, offset; diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index c0bdf6e..f018e55 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -127,6 +127,35 @@ FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPix) TRACE; } +void +FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, CARD32 src_pitch_offset, + CARD32 dst_pitch_offset, CARD32 datatype, int rop, + Pixel planemask) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + ACCEL_PREAMBLE(); + + RADEON_SWITCH_TO_2D(); + + BEGIN_ACCEL(5); + OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, + RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (datatype << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP[rop].rop | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS); + OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); + OUT_ACCEL_REG(RADEON_DP_CNTL, + ((info->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | + (info->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0))); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); + OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); + FINISH_ACCEL(); +} + static Bool FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, int xdir, int ydir, @@ -135,7 +164,6 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, { RINFO_FROM_SCREEN(pDst->drawable.pScreen); CARD32 datatype, src_pitch_offset, dst_pitch_offset; - ACCEL_PREAMBLE(); TRACE; @@ -151,30 +179,13 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); - RADEON_SWITCH_TO_2D(); - - BEGIN_ACCEL(5); - OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_SRC_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (datatype << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP[rop].rop | - RADEON_DP_SRC_SOURCE_MEMORY | - RADEON_GMC_CLR_CMP_CNTL_DIS); - OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); - OUT_ACCEL_REG(RADEON_DP_CNTL, - ((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | - (ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0))); - OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); - OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); - FINISH_ACCEL(); + FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset, + datatype, rop, planemask); return TRUE; } -static void +void FUNC_NAME(RADEONCopy)(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, |