diff options
-rw-r--r-- | man/radeon.man | 11 | ||||
-rw-r--r-- | src/radeon.h | 103 | ||||
-rw-r--r-- | src/radeon_accel.c | 190 | ||||
-rw-r--r-- | src/radeon_accelfuncs.c | 126 | ||||
-rw-r--r-- | src/radeon_commonfuncs.c | 186 | ||||
-rw-r--r-- | src/radeon_cursor.c | 91 | ||||
-rw-r--r-- | src/radeon_dga.c | 91 | ||||
-rw-r--r-- | src/radeon_dri.c | 85 | ||||
-rw-r--r-- | src/radeon_driver.c | 830 | ||||
-rw-r--r-- | src/radeon_exa.c | 463 | ||||
-rw-r--r-- | src/radeon_exa_funcs.c | 408 | ||||
-rw-r--r-- | src/radeon_exa_render.c | 799 | ||||
-rw-r--r-- | src/radeon_mergedfb.c | 20 | ||||
-rw-r--r-- | src/radeon_reg.h | 75 | ||||
-rw-r--r-- | src/radeon_render.c | 141 | ||||
-rw-r--r-- | src/radeon_video.c | 324 | ||||
-rw-r--r-- | src/radeon_video.h | 8 |
17 files changed, 3201 insertions, 750 deletions
diff --git a/man/radeon.man b/man/radeon.man index b08ba06..d594d5a 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -501,6 +501,17 @@ unsupported). The default is to .B enable Render acceleration. .TP +.BI "Option \*qAccelMethod\*q \*q" "string" \*q +Chooses between available acceleration architectures. Valid options are +.B XAA +and +.B EXA. +XAA is the traditional acceleration architecture and support for it is very +stable. EXA is a newer acceleration architecture with better performance for +the Render and Composite extensions, but the rendering code for it is newer and +possibly unstable. The default is +.B XAA. +.TP .BI "Option \*qDMAForXv\*q \*q" boolean \*q Try or don't try to use DMA for Xv image transfers. This will reduce CPU usage when playing big videos like DVDs, but may cause instabilities. diff --git a/src/radeon.h b/src/radeon.h index b1060cd..7150487 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -43,8 +43,15 @@ /* PCI support */ #include "xf86Pci.h" - /* XAA and Cursor Support */ +#ifdef USE_EXA +#include "exa.h" +#endif +#ifdef USE_XAA #include "xaa.h" +#include "xf86fbman.h" +#endif + + /* Exa and Cursor Support */ #include "vbe.h" #include "xf86Cursor.h" @@ -122,6 +129,7 @@ do { \ #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) + typedef struct { /* Common registers */ CARD32 ovr_clr; @@ -382,11 +390,25 @@ typedef struct { Bool PaletteSavedOnVT; /* Palette saved on last VT switch */ +#ifdef USE_EXA + ExaDriverRec exa; +#endif +#ifdef USE_XAA XAAInfoRecPtr accel; + int engineMode; +#define EXA_ENGINEMODE_UNKNOWN 0 +#define EXA_ENGINEMODE_2D 1 +#define EXA_ENGINEMODE_3D 2 +#endif Bool accelOn; xf86CursorInfoPtr cursor; - unsigned long cursor_start; +#ifdef USE_EXA + ExaOffscreenArea *cursorArea; +#endif + unsigned long cursor_offset; +#ifdef USE_XAA unsigned long cursor_end; +#endif Bool allowColorTiling; Bool tilingEnabled; /* mirror of sarea->tiling_enabled */ #ifdef ARGB_CURSOR @@ -395,11 +417,13 @@ typedef struct { int cursor_fg; int cursor_bg; +#ifdef USE_XAA /* * XAAForceTransBlit is used to change the behavior of the XAA * SetupForScreenToScreenCopy function, to make it DGA-friendly. */ Bool XAAForceTransBlit; +#endif int fifo_slots; /* Free slots in the FIFO (64 max) */ int pix24bpp; /* Depth of pixmap for 24bpp fb */ @@ -416,6 +440,7 @@ typedef struct { int xdir; int ydir; +#ifdef USE_XAA /* ScanlineScreenToScreenColorExpand support */ unsigned char *scratch_buffer[1]; unsigned char *scratch_save; @@ -432,7 +457,7 @@ typedef struct { int scanline_hpass; int scanline_x1clip; int scanline_x2clip; - +#endif /* Saved values for DashedTwoPointLine */ int dashLen; CARD32 dashPattern; @@ -539,6 +564,7 @@ typedef struct { int textureSize; int log2TexGran; +#ifdef USE_XAA CARD32 frontPitchOffset; CARD32 backPitchOffset; CARD32 depthPitchOffset; @@ -551,6 +577,7 @@ typedef struct { FBAreaPtr backArea; int depthTexLines; FBAreaPtr depthTexArea; +#endif /* Saved scissor values */ CARD32 sc_left; @@ -580,7 +607,6 @@ typedef struct { /* XVideo */ XF86VideoAdaptorPtr adaptor; void (*VideoTimerCallback)(ScrnInfoPtr, Time); - FBLinearPtr videoLinear; int videoKey; int RageTheatreCrystal; int RageTheatreTunerPort; @@ -603,19 +629,31 @@ typedef struct { CARD8 input[5]; } MM_TABLE; CARD16 video_decoder_type; - /* Render */ + + /* Render */ Bool RenderAccel; - Bool RenderInited3D; +#ifdef USE_XAA FBLinearPtr RenderTex; void (*RenderCallback)(ScrnInfoPtr); Time RenderTimeout; +#endif - /* general */ + /* general */ Bool showCache; OptionInfoPtr Options; + + Bool useEXA; #ifdef XFree86LOADER +#ifdef USE_EXA + XF86ModReqInfo exaReq; +#endif +#ifdef USE_XAA XF86ModReqInfo xaaReq; #endif +#endif + + /* X itself has the 3D context */ + Bool XInited3D; /* merged fb stuff, also covers clone modes */ Bool MergedFB; @@ -692,11 +730,22 @@ extern void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn); extern void RADEONChangeSurfaces(ScrnInfoPtr pScrn); extern Bool RADEONAccelInit(ScreenPtr pScreen); +#ifdef USE_EXA +extern Bool RADEONSetupMemEXA (ScreenPtr pScreen); +extern Bool RADEONDrawInitMMIO(ScreenPtr pScreen); +#ifdef XF86DRI +extern Bool RADEONDrawInitCP(ScreenPtr pScreen); +#endif +#endif +#ifdef USE_XAA extern void RADEONAccelInitMMIO(ScreenPtr pScreen, XAAInfoRecPtr a); +#endif extern void RADEONEngineInit(ScrnInfoPtr pScrn); extern Bool RADEONCursorInit(ScreenPtr pScreen); extern Bool RADEONDGAInit(ScreenPtr pScreen); +extern void RADEONInit3DEngine(ScrnInfoPtr pScrn); + extern int RADEONMinBits(int val); extern void RADEONInitVideo(ScreenPtr pScreen); @@ -707,7 +756,9 @@ extern void RADEONPllErrataAfterIndex(RADEONInfoPtr info); extern void RADEONPllErrataAfterData(RADEONInfoPtr info); #ifdef XF86DRI +#ifdef USE_XAA extern void RADEONAccelInitCP(ScreenPtr pScreen, XAAInfoRecPtr a); +#endif extern Bool RADEONDRIScreenInit(ScreenPtr pScreen); extern void RADEONDRICloseScreen(ScreenPtr pScreen); extern void RADEONDRIResume(ScreenPtr pScreen); @@ -723,10 +774,14 @@ extern CARD8* RADEONHostDataBlit(ScrnInfoPtr pScrn, unsigned int bpp, unsigned int w, CARD32 dstPitch, CARD32 *bufPitch, CARD8 **dst, unsigned int *h, unsigned int *hpass); -extern void RADEONHostDataBlitCopyPass(CARD8 *dst, CARD8 *src, +extern void RADEONHostDataBlitCopyPass(ScrnInfoPtr pScrn, + unsigned int bpp, + CARD8 *dst, CARD8 *src, unsigned int hpass, unsigned int dstPitch, unsigned int srcPitch); +extern void RADEONCopySwap(CARD8 *dst, CARD8 *src, unsigned int size, + int swap); extern Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10); extern Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn); @@ -907,19 +962,43 @@ do { \ #define RADEON_FLUSH_CACHE() \ do { \ BEGIN_RING(2); \ - OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB2D_DC_FLUSH); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH); \ ADVANCE_RING(); \ } while (0) #define RADEON_PURGE_CACHE() \ do { \ BEGIN_RING(2); \ - OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB2D_DC_FLUSH_ALL); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ ADVANCE_RING(); \ } while (0) #endif /* XF86DRI */ +static __inline__ void RADEON_MARK_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn) +{ +#ifdef USE_EXA + if (info->useEXA) + exaMarkSync(pScrn->pScreen); +#endif +#ifdef USE_XAA + if (!info->useEXA) + SET_SYNC_FLAG(info->accel); +#endif +} + +static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn) +{ +#ifdef USE_EXA + if (info->useEXA) + exaWaitSync(pScrn->pScreen); +#endif +#ifdef USE_XAA + if (!info->useEXA && info->accel) + info->accel->Sync(pScrn); +#endif +} + #endif /* _RADEON_H_ */ diff --git a/src/radeon_accel.c b/src/radeon_accel.c index d89568d..5cdabcb 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -93,6 +93,7 @@ /* X and server generic header files */ #include "xf86.h" + static struct { int rop; int pattern; @@ -160,6 +161,10 @@ void RADEONEngineFlush(ScrnInfoPtr pScrn) if (!(INREG(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY)) break; } + if (i == RADEON_TIMEOUT) { + RADEONTRACE(("DC flush timeout: %x\n", + INREG(RADEON_RB2D_DSTCACHE_CTLSTAT))); + } } /* Reset graphics card to known state */ @@ -342,9 +347,7 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) RADEONWaitForIdleMMIO(pScrn); -#ifdef RENDER - info->RenderInited3D = FALSE; -#endif + info->XInited3D = FALSE; } /* Initialize the acceleration hardware */ @@ -399,13 +402,15 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) RADEONEngineRestore(pScrn); } + #define ACCEL_MMIO #define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO #define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) #define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) #define FINISH_ACCEL() -#ifdef RENDER +#include "radeon_commonfuncs.c" +#if defined(RENDER) && defined(USE_XAA) #include "radeon_render.c" #endif #include "radeon_accelfuncs.c" @@ -426,7 +431,9 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) #define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) #define FINISH_ACCEL() ADVANCE_RING() -#ifdef RENDER + +#include "radeon_commonfuncs.c" +#if defined(RENDER) && defined(USE_XAA) #include "radeon_render.c" #endif #include "radeon_accelfuncs.c" @@ -656,14 +663,22 @@ RADEONHostDataBlit( } #if X_BYTE_ORDER == X_BIG_ENDIAN - BEGIN_RING(2); - if (bpp == 2) - OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_16BIT); - else if (bpp == 1) - OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT); - else - OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); - ADVANCE_RING(); + /* Swap doesn't work on R300 and later, it's handled during the + * copy to ind. buffer pass + */ + if (info->ChipFamily < CHIP_FAMILY_R300) { + BEGIN_RING(2); + if (bpp == 2) + OUT_RING_REG(RADEON_RBBM_GUICNTL, + RADEON_HOST_DATA_SWAP_HDW); + else if (bpp == 1) + OUT_RING_REG(RADEON_RBBM_GUICNTL, + RADEON_HOST_DATA_SWAP_32BIT); + else + OUT_RING_REG(RADEON_RBBM_GUICNTL, + RADEON_HOST_DATA_SWAP_NONE); + ADVANCE_RING(); + } #endif /*RADEON_PURGE_CACHE(); @@ -704,11 +719,61 @@ RADEONHostDataBlit( return ret; } +void RADEONCopySwap(CARD8 *dst, CARD8 *src, unsigned int size, int swap) +{ + switch(swap) { + case RADEON_HOST_DATA_SWAP_HDW: + { + unsigned int *d = (unsigned int *)dst; + unsigned int *s = (unsigned int *)src; + unsigned int nwords = size >> 2; + + for (; nwords > 0; --nwords, ++d, ++s) + *d = ((*s & 0xffff) << 16) | ((*s >> 16) & 0xffff); + return; + } + case RADEON_HOST_DATA_SWAP_32BIT: + { + unsigned int *d = (unsigned int *)dst; + unsigned int *s = (unsigned int *)src; + unsigned int nwords = size >> 2; + + for (; nwords > 0; --nwords, ++d, ++s) +#ifdef __powerpc__ + asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d)); +#else + *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) + | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24); +#endif + return; + } + case RADEON_HOST_DATA_SWAP_16BIT: + { + unsigned short *d = (unsigned short *)dst; + unsigned short *s = (unsigned short *)src; + unsigned int nwords = size >> 1; + + for (; nwords > 0; --nwords, ++d, ++s) +#ifdef __powerpc__ + asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d)); +#else + *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) + | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24); +#endif + return; + } + } + if (src != dst) + memmove(dst, src, size); +} + /* Copies a single pass worth of data for a hostdata blit set up by * RADEONHostDataBlit(). */ void RADEONHostDataBlitCopyPass( + ScrnInfoPtr pScrn, + unsigned int bpp, CARD8 *dst, CARD8 *src, unsigned int hpass, @@ -716,11 +781,27 @@ RADEONHostDataBlitCopyPass( unsigned int srcPitch ){ + RADEONInfoPtr info = RADEONPTR( pScrn ); + /* RADEONHostDataBlitCopy can return NULL ! */ if( (dst==NULL) || (src==NULL)) return; if ( dstPitch == srcPitch ) { +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (info->ChipFamily >= CHIP_FAMILY_R300) { + switch(bpp) { + case 1: + RADEONCopySwap(dst, src, hpass * dstPitch, + RADEON_HOST_DATA_SWAP_32BIT); + return; + case 2: + RADEONCopySwap(dst, src, hpass * dstPitch, + RADEON_HOST_DATA_SWAP_HDW); + return; + } + } +#endif memcpy( dst, src, hpass * dstPitch ); } else @@ -728,7 +809,22 @@ RADEONHostDataBlitCopyPass( unsigned int minPitch = min( dstPitch, srcPitch ); while ( hpass-- ) { +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (info->ChipFamily >= CHIP_FAMILY_R300) { + switch(bpp) { + case 1: + RADEONCopySwap(dst, src, minPitch, + RADEON_HOST_DATA_SWAP_32BIT); + goto next; + case 2: + RADEONCopySwap(dst, src, minPitch, + RADEON_HOST_DATA_SWAP_HDW); + goto next; + } + } +#endif memcpy( dst, src, minPitch ); + next: src += srcPitch; dst += dstPitch; } @@ -737,33 +833,67 @@ RADEONHostDataBlitCopyPass( #endif -/* Initialize XAA for supported acceleration and also initialize the - * graphics hardware for acceleration - */ Bool RADEONAccelInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - XAAInfoRecPtr a; - if (!(a = info->accel = XAACreateInfoRec())) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAACreateInfoRec Error\n"); - return FALSE; +#ifdef USE_EXA + if (info->useEXA) { +# ifdef XF86DRI + if (info->directRenderingEnabled) { + if (!RADEONDrawInitCP(pScreen)) + return FALSE; + } else +# endif /* XF86DRI */ + { + if (!RADEONDrawInitMMIO(pScreen)) + return FALSE; + } } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + XAAInfoRecPtr a; + + if (!(a = info->accel = XAACreateInfoRec())) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAACreateInfoRec Error\n"); + return FALSE; + } #ifdef XF86DRI - if (info->directRenderingEnabled) - RADEONAccelInitCP(pScreen, a); - else -#endif - RADEONAccelInitMMIO(pScreen, a); + if (info->directRenderingEnabled) + RADEONAccelInitCP(pScreen, a); + else +#endif /* XF86DRI */ + RADEONAccelInitMMIO(pScreen, a); - RADEONEngineInit(pScrn); + RADEONEngineInit(pScrn); - if (!XAAInit(pScreen, a)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Error\n"); - return FALSE; + if (!XAAInit(pScreen, a)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Error\n"); + return FALSE; + } } - +#endif /* USE_XAA */ return TRUE; } + +void RADEONInit3DEngine(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + +#ifdef XF86DRI + if (info->directRenderingEnabled) { + RADEONSAREAPrivPtr pSAREAPriv; + + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + RADEONInit3DEngineCP(pScrn); + } else +#endif + RADEONInit3DEngineMMIO(pScrn); + + info->XInited3D = TRUE; +} + diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c index c31e274..25d97de 100644 --- a/src/radeon_accelfuncs.c +++ b/src/radeon_accelfuncs.c @@ -95,89 +95,14 @@ #endif #endif -/* MMIO: - * - * Wait for the graphics engine to be completely idle: the FIFO has - * drained, the Pixel Cache is flushed, and the engine is idle. This is - * a standard "sync" function that will make the hardware "quiescent". - * - * CP: - * - * Wait until the CP is completely idle: the FIFO has drained and the CP - * is idle. - */ -void -FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int i = 0; - -#ifdef ACCEL_CP - /* Make sure the CP is idle first */ - if (info->CPStarted) { - int ret; - FLUSH_RING(); - - for (;;) { - do { - ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE); - if (ret && ret != -EBUSY) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "%s: CP idle %d\n", __FUNCTION__, ret); - } - } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT)); - - if (ret == 0) return; - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Idle timed out, resetting engine...\n"); - RADEONEngineReset(pScrn); - RADEONEngineRestore(pScrn); - - /* Always restart the engine when doing CP 2D acceleration */ - RADEONCP_RESET(pScrn, info); - RADEONCP_START(pScrn, info); - } - } -#endif - - RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); - - /* Wait for the engine to go idle */ - RADEONWaitForFifoFunction(pScrn, 64); - - for (;;) { - for (i = 0; i < RADEON_TIMEOUT; i++) { - if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) { - RADEONEngineFlush(pScrn); - return; - } - } - RADEONTRACE(("Idle timed out: %d entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Idle timed out, resetting engine...\n"); - RADEONEngineReset(pScrn); - RADEONEngineRestore(pScrn); -#ifdef XF86DRI - if (info->directRenderingEnabled) { - RADEONCP_RESET(pScrn, info); - RADEONCP_START(pScrn, info); - } -#endif - } -} +#ifdef USE_XAA /* This callback is required for multiheader cards using XAA */ static void FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; + /*RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO;*/ #ifdef ACCEL_MMIO @@ -775,6 +700,8 @@ FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); + info->scanline_bpp = 0; + /* Save for later clipping */ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl | RADEON_GMC_DST_CLIPPING @@ -812,9 +739,12 @@ FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, #if X_BYTE_ORDER == X_LITTLE_ENDIAN BEGIN_ACCEL(1); #else - BEGIN_ACCEL(2); + if (info->ChipFamily < CHIP_FAMILY_R300) { + BEGIN_ACCEL(2); - OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT); + OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT); + } else + BEGIN_ACCEL(1); #endif OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); @@ -939,6 +869,22 @@ FUNC_NAME(RADEONSubsequentScanline)(ScrnInfoPtr pScrn, #else /* ACCEL_CP */ +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (info->ChipFamily >= CHIP_FAMILY_R300) { + if (info->scanline_bpp == 16) { + RADEONCopySwap(info->scratch_buffer[bufno], + info->scratch_buffer[bufno], + info->scanline_words << 2, + RADEON_HOST_DATA_SWAP_HDW); + } else if (info->scanline_bpp < 15) { + RADEONCopySwap(info->scratch_buffer[bufno], + info->scratch_buffer[bufno], + info->scanline_words << 2, + RADEON_HOST_DATA_SWAP_32BIT); + } + } +#endif + if (--info->scanline_hpass) { info->scratch_buffer[bufno] += 4 * info->scanline_words; } else if (info->scanline_h) { @@ -994,12 +940,15 @@ FUNC_NAME(RADEONSetupForScanlineImageWrite)(ScrnInfoPtr pScrn, #if X_BYTE_ORDER == X_LITTLE_ENDIAN BEGIN_ACCEL(1); #else - BEGIN_ACCEL(2); - - if (bpp == 16) - OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW); - else - OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); + if (info->ChipFamily < CHIP_FAMILY_R300) { + BEGIN_ACCEL(2); + + if (bpp == 16) + OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW); + else + OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); + } else + BEGIN_ACCEL(1); #endif #endif OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); @@ -1225,7 +1174,8 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) = FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill); a->SubsequentScanlineCPUToScreenColorExpandFill = FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill); - a->SubsequentColorExpandScanline = FUNC_NAME(RADEONSubsequentScanline); + a->SubsequentColorExpandScanline + = FUNC_NAME(RADEONSubsequentScanline); /* Solid Lines */ a->SetupForSolidLine @@ -1394,4 +1344,6 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) #endif /* RENDER */ } +#endif /* USE_XAA */ + #undef FUNC_NAME diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c new file mode 100644 index 0000000..a71bf3a --- /dev/null +++ b/src/radeon_commonfuncs.c @@ -0,0 +1,186 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c,v 1.7tsi Exp $ */ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(ACCEL_MMIO) && defined(ACCEL_CP) +#error Cannot define both MMIO and CP acceleration! +#endif + +#if !defined(UNIXCPP) || defined(ANSICPP) +#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix +#else +#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix +#endif + +#ifdef ACCEL_MMIO +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO) +#else +#ifdef ACCEL_CP +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP) +#else +#error No accel type defined! +#endif +#endif + +static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + ACCEL_PREAMBLE(); + + if (info->ChipFamily >= CHIP_FAMILY_R300) { + /* Unimplemented */ + } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) || + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_R200)) { + + BEGIN_ACCEL(7); + if (info->ChipFamily == CHIP_FAMILY_RS300) { + OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS); + } else { + OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, 0); + } + OUT_ACCEL_REG(R200_PP_CNTL_X, 0); + OUT_ACCEL_REG(R200_PP_TXMULTI_CTL_0, 0); + OUT_ACCEL_REG(R200_SE_VTX_STATE_CNTL, 0); + OUT_ACCEL_REG(R200_RE_CNTL, 0x0); + /* XXX: correct? Want it to be like RADEON_VTX_ST?_NONPARAMETRIC */ + OUT_ACCEL_REG(R200_SE_VTE_CNTL, R200_VTX_ST_DENORMALIZED); + OUT_ACCEL_REG(R200_SE_VAP_CNTL, R200_VAP_FORCE_W_TO_ONE | + R200_VAP_VF_MAX_VTX_NUM); + FINISH_ACCEL(); + } else { + BEGIN_ACCEL(2); + if ((info->ChipFamily == CHIP_FAMILY_RADEON) || + (info->ChipFamily == CHIP_FAMILY_RV200)) + OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, 0); + else + OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS); + OUT_ACCEL_REG(RADEON_SE_COORD_FMT, + RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | + RADEON_VTX_ST0_NONPARAMETRIC | + RADEON_VTX_ST1_NONPARAMETRIC | + RADEON_TEX1_W_ROUTING_USE_W0); + FINISH_ACCEL(); + } + + BEGIN_ACCEL(5); + OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); + OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, 0x07ff07ff); + OUT_ACCEL_REG(RADEON_AUX_SC_CNTL, 0); + OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff); + OUT_ACCEL_REG(RADEON_SE_CNTL, RADEON_DIFFUSE_SHADE_GOURAUD | + RADEON_BFACE_SOLID | + RADEON_FFACE_SOLID | + RADEON_VTX_PIX_CENTER_OGL | + RADEON_ROUND_MODE_ROUND | + RADEON_ROUND_PREC_4TH_PIX); + FINISH_ACCEL(); +} + + +/* MMIO: + * + * Wait for the graphics engine to be completely idle: the FIFO has + * drained, the Pixel Cache is flushed, and the engine is idle. This is + * a standard "sync" function that will make the hardware "quiescent". + * + * CP: + * + * Wait until the CP is completely idle: the FIFO has drained and the CP + * is idle. + */ +void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i = 0; + +#ifdef ACCEL_CP + /* Make sure the CP is idle first */ + if (info->CPStarted) { + int ret; + + FLUSH_RING(); + + for (;;) { + do { + ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE); + if (ret && ret != -EBUSY) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s: CP idle %d\n", __FUNCTION__, ret); + } + } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT)); + + if (ret == 0) return; + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Idle timed out, resetting engine...\n"); + RADEONEngineReset(pScrn); + RADEONEngineRestore(pScrn); + + /* Always restart the engine when doing CP 2D acceleration */ + RADEONCP_RESET(pScrn, info); + RADEONCP_START(pScrn, info); + } + } +#endif + + RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS))); + + /* Wait for the engine to go idle */ + RADEONWaitForFifoFunction(pScrn, 64); + + for (;;) { + for (i = 0; i < RADEON_TIMEOUT; i++) { + if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) { + RADEONEngineFlush(pScrn); + return; + } + } + RADEONTRACE(("Idle timed out: %d entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS))); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Idle timed out, resetting engine...\n"); + RADEONEngineReset(pScrn); + RADEONEngineRestore(pScrn); +#ifdef XF86DRI + if (info->directRenderingEnabled) { + RADEONCP_RESET(pScrn, info); + RADEONCP_START(pScrn, info); + } +#endif + } +} diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c index c08550d..fc249ff 100644 --- a/src/radeon_cursor.c +++ b/src/radeon_cursor.c @@ -68,9 +68,7 @@ static CARD32 mono_cursor_color[] = { #define CURSOR_WIDTH 64 #define CURSOR_HEIGHT 64 -#define COMMON_CURSOR_SWAPPING_START() \ - if (info->accel && info->accel->Sync) \ - info->accel->Sync(pScrn); +#define COMMON_CURSOR_SWAPPING_START() RADEON_SYNC(info, pScrn) /* * The cursor bits are always 32bpp. On MSBFirst buses, @@ -108,7 +106,7 @@ static CARD32 mono_cursor_color[] = { static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_start); + CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_offset); int pixel, i; CURSOR_SWAPPING_DECL_MMIO @@ -173,7 +171,7 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); - OUTREG(RADEON_CUR_OFFSET, info->cursor_start + yorigin * stride); + OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + yorigin * stride); } else { OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) @@ -182,7 +180,7 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); OUTREG(RADEON_CUR2_OFFSET, - info->cursor_start + pScrn->fbOffset + yorigin * stride); + info->cursor_offset + pScrn->fbOffset + yorigin * stride); } } @@ -195,7 +193,7 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD8 *s = (CARD8 *)(pointer)image; - CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_start); + CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset); CARD32 save1 = 0; CARD32 save2 = 0; CARD8 chunk; @@ -279,7 +277,7 @@ static Bool RADEONUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - return info->cursor_start ? TRUE : FALSE; + return info->cursor_offset ? TRUE : FALSE; } #ifdef ARGB_CURSOR @@ -290,7 +288,7 @@ static Bool RADEONUseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->cursor_start && + if (info->cursor_offset && pCurs->bits->height <= CURSOR_HEIGHT && pCurs->bits->width <= CURSOR_WIDTH) return TRUE; return FALSE; @@ -300,7 +298,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_start); + CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset); int x, y, w, h; CARD32 save1 = 0; CARD32 save2 = 0; @@ -361,6 +359,18 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) #endif +#ifdef USE_EXA +static void +ATICursorSave(ScreenPtr pScreen, ExaOffscreenArea *area) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->cursorArea = NULL; + info->cursor_offset = 0; +} +#endif + /* Initialize hardware cursor support. */ Bool RADEONCursorInit(ScreenPtr pScreen) @@ -368,7 +378,6 @@ Bool RADEONCursorInit(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); xf86CursorInfoPtr cursor; - FBAreaPtr fbarea; int width; int width_bytes; int height; @@ -405,29 +414,49 @@ Bool RADEONCursorInit(ScreenPtr pScreen) width = pScrn->displayWidth; width_bytes = width * (pScrn->bitsPerPixel / 8); height = (size_bytes + width_bytes - 1) / width_bytes; - fbarea = xf86AllocateOffscreenArea(pScreen, - width, - height, - 256, - NULL, - NULL, - NULL); - - if (!fbarea) { - info->cursor_start = 0; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + +#ifdef USE_EXA + if (info->useEXA) { + info->cursorArea = exaOffscreenAlloc(pScreen, size_bytes, + 128, TRUE, ATICursorSave, info); + + if (!info->cursorArea) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Hardware cursor disabled" + " due to insufficient offscreen memory\n"); + info->cursor_offset = 0; + } else { + info->cursor_offset = info->cursorArea->offset; + } + + RADEONTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n", + info->cursor_offset, + info->cursor_offset + info->cursorArea->size)); + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + FBAreaPtr fbarea; + + fbarea = xf86AllocateOffscreenArea(pScreen, width, height, + 256, NULL, NULL, NULL); + + if (!fbarea) { + info->cursor_offset = 0; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Hardware cursor disabled" " due to insufficient offscreen memory\n"); - } else { - info->cursor_start = RADEON_ALIGN((fbarea->box.x1 + - fbarea->box.y1 * width) * - info->CurrentLayout.pixel_bytes, - 256); - info->cursor_end = info->cursor_start + size_bytes; + } else { + info->cursor_offset = RADEON_ALIGN((fbarea->box.x1 + + fbarea->box.y1 * width) * + info->CurrentLayout.pixel_bytes, + 256); + info->cursor_end = info->cursor_offset + size_bytes; + } + RADEONTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n", + info->cursor_offset, info->cursor_end)); } - - RADEONTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n", - info->cursor_start, info->cursor_end)); +#endif return xf86InitCursor(pScreen, cursor); } diff --git a/src/radeon_dga.c b/src/radeon_dga.c index 9c70d78..06fc62e 100644 --- a/src/radeon_dga.c +++ b/src/radeon_dga.c @@ -61,9 +61,10 @@ static int RADEON_GetViewport(ScrnInfoPtr); static void RADEON_SetViewport(ScrnInfoPtr, int, int, int); static void RADEON_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); static void RADEON_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +#ifdef USE_XAA static void RADEON_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, unsigned long); - +#endif static DGAModePtr RADEONSetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, @@ -112,7 +113,19 @@ SECOND_PASS: if (pixmap) currentMode->flags |= DGA_PIXMAP_AVAILABLE; - if (info->accel) { +#ifdef USE_EXA + if (info->useEXA) { + /* We need to fill in RADEON_FillRect and RADEON_BlitRect and + * connect them in RADEONDGAInit before turning these on. + */ + /*if (info->exa.accel.PrepareSolid && info->exa.accel.Solid) + currentMode->flags |= DGA_FILL_RECT; + if (info->exa.accel.PrepareCopy && info->exa.accel.Copy) + currentMode->flags |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS;*/ + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA && info->accel) { if (info->accel->SetupForSolidFill && info->accel->SubsequentSolidFillRect) currentMode->flags |= DGA_FILL_RECT; @@ -124,6 +137,8 @@ SECOND_PASS: DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS)) currentMode->flags &= ~DGA_CONCURRENT_ACCESS; } +#endif /* USE_XAA */ + if (pMode->Flags & V_DBLSCAN) currentMode->flags |= DGA_DOUBLESCAN; if (pMode->Flags & V_INTERLACE) @@ -237,7 +252,19 @@ Bool RADEONDGAInit(ScreenPtr pScreen) info->DGAFuncs.BlitRect = NULL; info->DGAFuncs.BlitTransRect = NULL; - if (info->accel) { +#ifdef USE_EXA + /*info->DGAFuncs.Sync = info->exa.accel->Sync;*/ + if (info->useEXA) { + /*if (info->exa.accel.PrepareSolid && info->exa.accel.Solid) { + info->DGAFuncs.FillRect = RADEON_FillRect; + } + if (info->exa.accel.PrepareCopy && info->exa.accel.Copy) { + info->DGAFuncs.BlitRect = RADEON_BlitRect; + }*/ + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA && info->accel) { info->DGAFuncs.Sync = info->accel->Sync; if (info->accel->SetupForSolidFill && info->accel->SubsequentSolidFillRect) @@ -248,6 +275,7 @@ Bool RADEONDGAInit(ScreenPtr pScreen) info->DGAFuncs.BlitTransRect = RADEON_BlitTransRect; } } +#endif /* USE_XAA */ return DGAInit(pScreen, &info->DGAFuncs, modes, num); } @@ -332,17 +360,33 @@ static void RADEON_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) info->DGAViewportStatus = 0; /* FIXME */ } + static void RADEON_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color) { RADEONInfoPtr info = RADEONPTR(pScrn); - (*info->accel->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0)); - (*info->accel->SubsequentSolidFillRect)(pScrn, x, y, w, h); +#ifdef USE_EXA + /* XXX */ + if (info->useEXA) { + /* + info->exa.accel.PrepareSolid(pScrn, color, GXcopy, (CARD32)(~0)); + info->exa.accel.Solid(pScrn, x, y, x+w, y+h); + info->exa.accel.DoneSolid(); + */ + RADEON_MARK_SYNC(info, pScrn); + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + (*info->accel->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0)); + (*info->accel->SubsequentSolidFillRect)(pScrn, x, y, w, h); + if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel) + RADEON_MARK_SYNC(info, pScrn); + } +#endif /* USE_XAA */ - if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel) - SET_SYNC_FLAG(info->accel); } static void RADEON_BlitRect(ScrnInfoPtr pScrn, @@ -353,15 +397,30 @@ static void RADEON_BlitRect(ScrnInfoPtr pScrn, int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; int ydir = (srcy < dsty) ? -1 : 1; - (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, - GXcopy, (CARD32)(~0), -1); - (*info->accel->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, - dstx, dsty, w, h); - - if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel) - SET_SYNC_FLAG(info->accel); + #ifdef USE_EXA + /* XXX */ + if (info->useEXA) { + /* + info->exa.accel.PrepareCopy(pScrn, color, GXcopy, (CARD32)(~0)); + info->exa.accel.Copy(pScrn, srcx, srcy, dstx, dsty, w, h); + info->exa.accel.DoneCopy(); + */ + RADEON_MARK_SYNC(info, pScrn); + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, + GXcopy, (CARD32)(~0), -1); + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, + dstx, dsty, w, h); + if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel) + RADEON_MARK_SYNC(info, pScrn); + } +#endif /* USE_XAA */ } +#ifdef USE_XAA static void RADEON_BlitTransRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long color) @@ -371,7 +430,6 @@ static void RADEON_BlitTransRect(ScrnInfoPtr pScrn, int ydir = (srcy < dsty) ? -1 : 1; info->XAAForceTransBlit = TRUE; - (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, (CARD32)(~0), color); @@ -381,8 +439,9 @@ static void RADEON_BlitTransRect(ScrnInfoPtr pScrn, dstx, dsty, w, h); if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel) - SET_SYNC_FLAG(info->accel); + RADEON_MARK_SYNC(info, pScrn); } +#endif /* USE_XAA */ static Bool RADEON_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, diff --git a/src/radeon_dri.c b/src/radeon_dri.c index 8e2fe44..892e5d5 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -42,6 +42,7 @@ /* Driver data structures */ #include "radeon.h" +#include "radeon_video.h" #include "radeon_reg.h" #include "radeon_macros.h" #include "radeon_dri.h" @@ -347,17 +348,15 @@ static void RADEONEnterServer(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); -#ifdef RENDER RADEONSAREAPrivPtr pSAREAPriv; -#endif - if (info->accel) info->accel->NeedToSync = TRUE; -#ifdef RENDER + RADEON_MARK_SYNC(info, pScrn); + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen)) - info->RenderInited3D = FALSE; -#endif + info->XInited3D = FALSE; + /* TODO: Fix this more elegantly. * Sometimes (especially with multiple DRI clients), this code @@ -528,6 +527,7 @@ static void RADEONDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx) static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 indx) { +#ifdef USE_XAA ScreenPtr pScreen = pParent->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -551,6 +551,10 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, int dx = pParent->drawable.x - ptOldOrg.x; int dy = pParent->drawable.y - ptOldOrg.y; + /* XXX: Fix in EXA case. */ + if (info->useEXA) + return; + /* If the copy will overlap in Y, reverse the order */ if (dy > 0) { ydir = -1; @@ -683,6 +687,7 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, DEALLOCATE_LOCAL(pboxNew1); info->accel->NeedToSync = TRUE; +#endif /* USE_XAA */ } static void RADEONDRIInitGARTValues(RADEONInfoPtr info) @@ -1183,7 +1188,10 @@ static void RADEONDRICPInit(ScrnInfoPtr pScrn) /* Make sure the CP is on for the X server */ RADEONCP_START(pScrn, info); - info->dst_pitch_offset = info->frontPitchOffset; +#ifdef USE_XAA + if (!info->useEXA) + info->dst_pitch_offset = info->frontPitchOffset; +#endif } @@ -1276,7 +1284,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) RADEON_VERSION_MAJOR_TILED : RADEON_VERSION_MAJOR; pDRIInfo->ddxDriverMinorVersion = RADEON_VERSION_MINOR; pDRIInfo->ddxDriverPatchVersion = RADEON_VERSION_PATCH; - pDRIInfo->frameBufferPhysicalAddress = info->LinearAddr; + pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr; pDRIInfo->frameBufferSize = info->FbMapSize; pDRIInfo->frameBufferStride = (pScrn->displayWidth * info->CurrentLayout.pixel_bytes); @@ -1602,7 +1610,7 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) #endif /* Have shadowfb run only while there is 3d active. */ - if (info->allowPageFlip /* && info->drmMinor >= 3 */) { + if (!info->useEXA && info->allowPageFlip /* && info->drmMinor >= 3 */) { ShadowFBInit( pScreen, RADEONDRIRefreshArea ); } else { info->allowPageFlip = 0; @@ -1795,6 +1803,8 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) return; +#ifdef USE_XAA + /* XXX: implement for EXA */ /* pretty much a hack. */ if (info->tilingEnabled) info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; @@ -1815,6 +1825,7 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) } } info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; +#endif /* USE_XAA */ } static void RADEONEnablePageFlip(ScreenPtr pScreen) @@ -1823,6 +1834,8 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); +#ifdef USE_XAA + /* XXX: Fix in EXA case */ if (info->allowPageFlip) { /* pretty much a hack. */ if (info->tilingEnabled) @@ -1843,6 +1856,7 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; pSAREAPriv->pfAllowPageFlip = 1; } +#endif /* USE_XAA */ } static void RADEONDisablePageFlip(ScreenPtr pScreen) @@ -1874,6 +1888,21 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) FBAreaPtr fbarea; int width, height; + info->have3DWindows = 1; + + RADEONChangeSurfaces(pScrn); + RADEONEnablePageFlip(pScreen); + + if (info->cursor_offset != 0) + xf86ForceHWCursor (pScreen, TRUE); + +#ifdef USE_XAA + /* EXA allocates these areas up front, so it doesn't do the following + * stuff. + */ + if (info->useEXA) + return; + /* reserve offscreen area for back and depth buffers and textures */ /* If we still have an area for the back buffer reserved, free it @@ -1889,15 +1918,21 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0); - /* Free Xv linear offscreen memory if necessary */ + /* Free Xv linear offscreen memory if necessary + * FIXME: This is hideous. What about telling xv "oh btw you have no memory + * any more?" -- anholt + */ if (height < (info->depthTexLines + info->backLines)) { - xf86FreeOffscreenLinear(info->videoLinear); - info->videoLinear = NULL; + RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr; + xf86FreeOffscreenLinear((FBLinearPtr)portPriv->video_memory); + portPriv->video_memory = NULL; xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0); } /* Reserve placeholder area so the other areas will match the * pre-calculated offsets + * FIXME: We may have other locked allocations and thus this would allocate + * in the wrong place. The XV surface allocations seem likely. -- anholt */ fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, height @@ -1929,14 +1964,7 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) "experience screen corruption\n"); xf86FreeOffscreenArea(fbarea); - - info->have3DWindows = 1; - - RADEONChangeSurfaces(pScrn); - RADEONEnablePageFlip(pScreen); - - if (info->cursor_start) - xf86ForceHWCursor (pScreen, TRUE); +#endif /* USE_XAA */ } static void RADEONDRITransitionTo2d(ScreenPtr pScreen) @@ -1952,22 +1980,29 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) /* Shut down shadowing if we've made it back to the front page */ if (pSAREAPriv->pfCurrentPage == 0) { RADEONDisablePageFlip(pScreen); - xf86FreeOffscreenArea(info->backArea); - info->backArea = NULL; +#ifdef USE_XAA + if (!info->useEXA) { + xf86FreeOffscreenArea(info->backArea); + info->backArea = NULL; + } +#endif } else { xf86DrvMsg(pScreen->myNum, X_WARNING, "[dri] RADEONDRITransitionTo2d: " "kernel failed to unflip buffers.\n"); } - xf86FreeOffscreenArea(info->depthTexArea); +#ifdef USE_XAA + if (!info->useEXA) + xf86FreeOffscreenArea(info->depthTexArea); +#endif info->have3DWindows = 0; RADEONChangeSurfaces(pScrn); - if (info->cursor_start) - xf86ForceHWCursor (pScreen, FALSE); + if (info->cursor_offset != 0) + xf86ForceHWCursor (pScreen, FALSE); } void RADEONDRIAllocatePCIGARTTable(ScreenPtr pScreen) diff --git a/src/radeon_driver.c b/src/radeon_driver.c index b49b962..c082a07 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -96,13 +96,12 @@ #include "xf86cmap.h" #include "vbe.h" - /* fbdevhw & vgaHW definitions */ + /* fbdevhw * vgaHW definitions */ #ifdef WITH_VGAHW #include "vgaHW.h" #endif #include "fbdevhw.h" - /* DPMS support. */ #define DPMS_SERVER #include <X11/extensions/dpms.h> @@ -193,7 +192,8 @@ typedef enum { OPTION_BIOS_HOTKEYS, OPTION_VGA_ACCESS, OPTION_REVERSE_DDC, - OPTION_LVDS_PROBE_PLL + OPTION_LVDS_PROBE_PLL, + OPTION_ACCELMETHOD } RADEONOpts; static const OptionInfoRec RADEONOptions[] = { @@ -255,6 +255,7 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_VGA_ACCESS, "VGAAccess", OPTV_BOOLEAN, {0}, TRUE }, { OPTION_REVERSE_DDC, "ReverseDDC", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -315,12 +316,30 @@ static const char *fbSymbols[] = { NULL }; + +#ifdef USE_EXA +static const char *exaSymbols[] = { + "exaDriverInit", + "exaDriverFini", + "exaOffscreenAlloc", + "exaOffscreenFree", + "exaGetPixmapOffset", + "exaGetPixmapPitch", + "exaGetPixmapSize", + "exaMarkSync", + "exaWaitSync", + NULL +}; +#endif /* USE_EXA */ + +#ifdef USE_XAA static const char *xaaSymbols[] = { "XAACreateInfoRec", "XAADestroyInfoRec", "XAAInit", NULL }; +#endif /* USE_XAA */ #if 0 static const char *xf8_32bppSymbols[] = { @@ -434,7 +453,12 @@ void RADEONLoaderRefSymLists(void) vgahwSymbols, #endif fbSymbols, +#ifdef USE_EXA + exaSymbols, +#endif +#ifdef USE_XAA xaaSymbols, +#endif #if 0 xf8_32bppSymbols, #endif @@ -3963,7 +3987,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->allowColorTiling ? 2048 : 64 * pScrn->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ - info->MaxLines, /* maxHeight */ + info->MaxLines, /* maxHeight */ pScrn->display->virtualX, pScrn->display->virtualY, info->FbMapSize, @@ -4032,7 +4056,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->allowColorTiling ? 2048 : 64 * pScrn->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ - info->MaxLines, /* maxHeight */ + info->MaxLines, /* maxHeight */ pScrn->display->virtualX, pScrn->display->virtualY, info->FbMapSize, @@ -4199,31 +4223,72 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) { #ifdef XFree86LOADER RADEONInfoPtr info = RADEONPTR(pScrn); + MessageType from; +#if defined(USE_EXA) && defined(USE_XAA) + char *optstr; +#endif if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { int errmaj = 0, errmin = 0; - info->xaaReq.majorversion = 1; - info->xaaReq.minorversion = 2; + from = X_DEFAULT; +#if defined(USE_EXA) +#if defined(USE_XAA) + optstr = (char *)xf86GetOptValString(info->Options, OPTION_ACCELMETHOD); + if (optstr != NULL) { + if (xf86NameCmp(optstr, "EXA") == 0) { + from = X_CONFIG; + info->useEXA = TRUE; + } else if (xf86NameCmp(optstr, "XAA") == 0) { + from = X_CONFIG; + } + } +#else /* USE_XAA */ + info->useEXA = TRUE; +#endif /* !USE_XAA */ +#endif /* USE_EXA */ + xf86DrvMsg(pScrn->scrnIndex, from, + "Using %s acceleration architecture\n", + info->useEXA ? "EXA" : "XAA"); + +#ifdef USE_EXA + if (info->useEXA) { + info->exaReq.majorversion = 1; + info->exaReq.minorversion = 0; - if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL, - &info->xaaReq, &errmaj, &errmin)) { - info->xaaReq.minorversion = 1; + if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, + &info->exaReq, &errmaj, &errmin)) { + LoaderErrorMsg(NULL, "exa", errmaj, errmin); + return FALSE; + } + xf86LoaderReqSymLists(exaSymbols, NULL); + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + info->xaaReq.majorversion = 1; + info->xaaReq.minorversion = 2; if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL, - &info->xaaReq, &errmaj, &errmin)) { - info->xaaReq.minorversion = 0; + &info->xaaReq, &errmaj, &errmin)) { + info->xaaReq.minorversion = 1; if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL, &info->xaaReq, &errmaj, &errmin)) { - LoaderErrorMsg(NULL, "xaa", errmaj, errmin); - return FALSE; + info->xaaReq.minorversion = 0; + + if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL, + &info->xaaReq, &errmaj, &errmin)) { + LoaderErrorMsg(NULL, "xaa", errmaj, errmin); + return FALSE; + } } } + xf86LoaderReqSymLists(xaaSymbols, NULL); } - xf86LoaderReqSymLists(xaaSymbols, NULL); +#endif /* USE_XAA */ } -#endif +#endif /* XFree86Loader */ return TRUE; } @@ -4376,6 +4441,11 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) 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; + } } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", @@ -4876,7 +4946,8 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, if (info->CPStarted) DRILock(pScrn->pScreen, 0); #endif - if (info->accelOn && pScrn->pScreen) info->accel->Sync(pScrn); + if (info->accelOn && pScrn->pScreen) + RADEON_SYNC(info, pScrn); if (info->FBDev) { fbdevHWLoadPalette(pScrn, numColors, indices, colors, pVisual); @@ -4999,10 +5070,13 @@ static void RADEONBlockHandler(int i, pointer blockData, RADEONInfoPtr info = RADEONPTR(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) + if (info->directRenderingEnabled) { FLUSH_RING(); + } +#endif +#ifdef USE_EXA + info->engineMode = EXA_ENGINEMODE_UNKNOWN; #endif - pScreen->BlockHandler = info->BlockHandler; (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); pScreen->BlockHandler = RADEONBlockHandler; @@ -5010,12 +5084,326 @@ static void RADEONBlockHandler(int i, pointer blockData, if (info->VideoTimerCallback) (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds); -#ifdef RENDER +#if defined(RENDER) && defined(USE_XAA) if(info->RenderCallback) (*info->RenderCallback)(pScrn); #endif +} + + +#ifdef USE_XAA +#ifdef XF86DRI +Bool RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + int width_bytes = pScrn->displayWidth * cpp; + int bufferSize; + int depthSize; + int l; + int scanlines; + BoxRec MemBox; + FBAreaPtr fbarea; + + info->frontOffset = 0; + info->frontPitch = pScrn->displayWidth; + info->backPitch = pScrn->displayWidth; + + /* make sure we use 16 line alignment for tiling (8 might be enough). + * Might need that for non-XF86DRI too? + */ + if (info->allowColorTiling) { + bufferSize = (((pScrn->virtualY + 15) & ~15) * width_bytes + + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN; + } else { + bufferSize = (pScrn->virtualY * width_bytes + + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN; + } + + /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels, + * which is always the case if color tiling is used due to color pitch + * but not necessarily otherwise, and its height a multiple of 16 lines. + */ + info->depthPitch = (pScrn->displayWidth + 31) & ~31; + depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch + * cpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); + + switch (info->CPMode) { + case RADEON_DEFAULT_CP_PIO_MODE: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n"); + break; + case RADEON_DEFAULT_CP_BM_MODE: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n"); + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n"); + break; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB GART aperture\n", info->gartSize); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB for the ring buffer\n", info->ringSize); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB for vertex/indirect buffers\n", info->bufSize); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB for GART textures\n", info->gartTexSize); + + /* Try for front, back, depth, and three framebuffers worth of + * pixmap cache. Should be enough for a fullscreen background + * image plus some leftovers. + */ + info->textureSize = info->FbMapSize - 5 * bufferSize - depthSize; + + /* If that gives us less than half the available memory, let's + * be greedy and grab some more. Sorry, I care more about 3D + * performance than playing nicely, and you'll get around a full + * framebuffer's worth of pixmap cache anyway. + */ + if (info->textureSize < (int)info->FbMapSize / 2) { + info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize; + } + if (info->textureSize < (int)info->FbMapSize / 2) { + info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; + } + + /* If there's still no space for textures, try without pixmap cache, but + * never use the reserved space, the space hw cursor and PCIGART table might + * use. + */ + if (info->textureSize < 0) { + info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize + - 2 * width_bytes - 16384 - RADEON_PCIGART_TABLE_SIZE; + } + + /* Check to see if there is more room available after the 8192nd + * scanline for textures + */ + /* FIXME: what's this good for? condition is pretty much impossible to meet */ + if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize + > info->textureSize) { + info->textureSize = + info->FbMapSize - 8192*width_bytes - bufferSize - depthSize; + } + + /* If backbuffer is disabled, don't allocate memory for it */ + if (info->noBackBuffer) { + info->textureSize += bufferSize; + } + + /* RADEON_BUFFER_ALIGN is not sufficient for backbuffer! + At least for pageflip + color tiling, need to make sure it's 16 scanlines aligned, + otherwise the copy-from-front-to-back will fail (width_bytes * 16 will also guarantee + it's still 4kb aligned for tiled case). Need to round up offset (might get into cursor + area otherwise). + This might cause some space at the end of the video memory to be unused, since it + can't be used (?) due to that log_tex_granularity thing??? + Could use different copyscreentoscreen function for the pageflip copies + (which would use different src and dst offsets) to avoid this. */ + if (info->allowColorTiling && !info->noBackBuffer) { + info->textureSize = info->FbMapSize - ((info->FbMapSize - info->textureSize + + width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes * 16); + } + if (info->textureSize > 0) { + l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) + l = RADEON_LOG_TEX_GRANULARITY; + /* Round the texture size up to the nearest whole number of + * texture regions. Again, be greedy about this, don't + * round down. + */ + info->log2TexGran = l; + info->textureSize = (info->textureSize >> l) << l; + } else { + info->textureSize = 0; + } + + /* Set a minimum usable local texture heap size. This will fit + * two 256x256x32bpp textures. + */ + if (info->textureSize < 512 * 1024) { + info->textureOffset = 0; + info->textureSize = 0; + } + + if (info->allowColorTiling && !info->noBackBuffer) { + info->textureOffset = ((info->FbMapSize - info->textureSize) / + (width_bytes * 16)) * (width_bytes * 16); + } + else { + /* Reserve space for textures */ + info->textureOffset = ((info->FbMapSize - info->textureSize + + RADEON_BUFFER_ALIGN) & + ~(CARD32)RADEON_BUFFER_ALIGN); + } + + /* Reserve space for the shared depth + * buffer. + */ + info->depthOffset = ((info->textureOffset - depthSize + + RADEON_BUFFER_ALIGN) & + ~(CARD32)RADEON_BUFFER_ALIGN); + + /* Reserve space for the shared back buffer */ + if (info->noBackBuffer) { + info->backOffset = info->depthOffset; + } else { + info->backOffset = ((info->depthOffset - bufferSize + + RADEON_BUFFER_ALIGN) & + ~(CARD32)RADEON_BUFFER_ALIGN); + } + + info->backY = info->backOffset / width_bytes; + info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp; + + scanlines = info->FbMapSize / width_bytes; + if (scanlines > 8191) + scanlines = 8191; + + MemBox.x1 = 0; + MemBox.y1 = 0; + MemBox.x2 = pScrn->displayWidth; + MemBox.y2 = scanlines; + + if (!xf86InitFBManager(pScreen, &MemBox)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Memory manager initialization to " + "(%d,%d) (%d,%d) failed\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + return FALSE; + } else { + int width, height; + + xf86DrvMsg(scrnIndex, X_INFO, + "Memory manager initialized to (%d,%d) (%d,%d)\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + /* why oh why can't we just request modes which are guaranteed to be 16 lines + aligned... sigh */ + if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, + info->allowColorTiling ? + ((pScrn->virtualY + 15) & ~15) + - pScrn->virtualY + 2 : 2, + 0, NULL, NULL, + NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved area from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); + } + + RADEONDRIAllocatePCIGARTTable(pScreen); + + if (xf86QueryLargestOffscreenArea(pScreen, &width, + &height, 0, 0, 0)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + + /* Lines in offscreen area needed for depth buffer and + * textures + */ + info->depthTexLines = (scanlines + - info->depthOffset / width_bytes); + info->backLines = (scanlines + - info->backOffset / width_bytes + - info->depthTexLines); + info->backArea = NULL; + } else { + xf86DrvMsg(scrnIndex, X_ERROR, + "Unable to determine largest offscreen area " + "available\n"); + return FALSE; + } + } + + xf86DrvMsg(scrnIndex, X_INFO, + "Will use back buffer at offset 0x%x\n", + info->backOffset); + xf86DrvMsg(scrnIndex, X_INFO, + "Will use depth buffer at offset 0x%x\n", + info->depthOffset); + xf86DrvMsg(scrnIndex, X_INFO, + "Will use %d kb for PCI GART table at offset 0x%x\n", + info->pciGartSize/1024, info->pciGartOffset); + xf86DrvMsg(scrnIndex, X_INFO, + "Will use %d kb for textures at offset 0x%x\n", + info->textureSize/1024, info->textureOffset); + + info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | + ((info->frontOffset + info->fbLocation) >> 10)); + + info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | + ((info->backOffset + info->fbLocation) >> 10)); + + info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | + ((info->depthOffset + info->fbLocation) >> 10)); +} +#endif /* XF86DRI */ + +Bool RADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + BoxRec MemBox; + int y2; + + int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; + MemBox.x1 = 0; + MemBox.y1 = 0; + MemBox.x2 = pScrn->displayWidth; + y2 = info->FbMapSize / width_bytes; + if (y2 >= 32768) + y2 = 32767; /* because MemBox.y2 is signed short */ + MemBox.y2 = y2; + + /* The acceleration engine uses 14 bit + * signed coordinates, so we can't have any + * drawable caches beyond this region. + */ + if (MemBox.y2 > 8191) + MemBox.y2 = 8191; + + if (!xf86InitFBManager(pScreen, &MemBox)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Memory manager initialization to " + "(%d,%d) (%d,%d) failed\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + return FALSE; + } else { + int width, height; + FBAreaPtr fbarea; + + xf86DrvMsg(scrnIndex, X_INFO, + "Memory manager initialized to (%d,%d) (%d,%d)\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, + info->allowColorTiling ? + ((pScrn->virtualY + 15) & ~15) + - pScrn->virtualY + 2 : 2, + 0, NULL, NULL, + NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved area from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); + } + if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, + 0, 0, 0)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + } + } } +#endif /* USE_XAA */ /* Called at the start of each server generation. */ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, @@ -5023,8 +5411,7 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - BoxRec MemBox; - int y2; + int hasDRI = 0; #ifdef RENDER int subPixelOrder = SubPixelUnknown; char* s; @@ -5061,6 +5448,13 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } +#if 0 + if (info->allowColorTiling && info->useEXA) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Color tiling not supported yet with EXA, disabling\n"); + info->allowColorTiling = FALSE; + } +#endif if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling not supported with virtual x resolutions larger than %d, disabling\n", @@ -5179,6 +5573,8 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Depth moves disabled by default\n"); } + + hasDRI = info->directRenderingEnabled; #endif RADEONSetFBLocation(pScrn); @@ -5229,300 +5625,25 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } #endif /* Memory manager setup */ -#ifdef XF86DRI - if (info->directRenderingEnabled) { - FBAreaPtr fbarea; - int cpp = info->CurrentLayout.pixel_bytes; - int width_bytes = pScrn->displayWidth * cpp; - int bufferSize; - int depthSize; - int l; - int scanlines; - - info->frontOffset = 0; - info->frontPitch = pScrn->displayWidth; - info->backPitch = pScrn->displayWidth; - /* make sure we use 16 line alignment for tiling (8 might be enough). - Might need that for non-XF86DRI too? */ - if (info->allowColorTiling) { - bufferSize = (((pScrn->virtualY + 15) & ~15) * width_bytes - + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN; - } - else { - bufferSize = (pScrn->virtualY * width_bytes - + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN; - } - /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels, - * which is always the case if color tiling is used due to color pitch - * but not necessarily otherwise, and its height a multiple of 16 lines. - */ - info->depthPitch = (pScrn->displayWidth + 31) & ~31; - depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch - * cpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); - - switch (info->CPMode) { - case RADEON_DEFAULT_CP_PIO_MODE: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n"); - break; - case RADEON_DEFAULT_CP_BM_MODE: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n"); - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n"); - break; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB GART aperture\n", info->gartSize); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB for the ring buffer\n", info->ringSize); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB for vertex/indirect buffers\n", info->bufSize); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB for GART textures\n", info->gartTexSize); - - /* Try for front, back, depth, and three framebuffers worth of - * pixmap cache. Should be enough for a fullscreen background - * image plus some leftovers. - */ - info->textureSize = info->FbMapSize - 5 * bufferSize - depthSize; - - /* If that gives us less than half the available memory, let's - * be greedy and grab some more. Sorry, I care more about 3D - * performance than playing nicely, and you'll get around a full - * framebuffer's worth of pixmap cache anyway. - */ - if (info->textureSize < (int)info->FbMapSize / 2) { - info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize; - } - if (info->textureSize < (int)info->FbMapSize / 2) { - info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; - } - /* If there's still no space for textures, try without pixmap cache, but never use - the reserved space, the space hw cursor and PCIGART table might use */ - if (info->textureSize < 0) { - info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize - - 2 * width_bytes - 16384 - RADEON_PCIGART_TABLE_SIZE; - } - - /* Check to see if there is more room available after the 8192nd - scanline for textures */ - /* FIXME: what's this good for? condition is pretty much impossible to meet */ - if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize - > info->textureSize) { - info->textureSize = - info->FbMapSize - 8192*width_bytes - bufferSize - depthSize; - } - - /* If backbuffer is disabled, don't allocate memory for it */ - if (info->noBackBuffer) { - info->textureSize += bufferSize; - } - - /* RADEON_BUFFER_ALIGN is not sufficient for backbuffer! - At least for pageflip + color tiling, need to make sure it's 16 scanlines aligned, - otherwise the copy-from-front-to-back will fail (width_bytes * 16 will also guarantee - it's still 4kb aligned for tiled case). Need to round up offset (might get into cursor - area otherwise). - This might cause some space at the end of the video memory to be unused, since it - can't be used (?) due to that log_tex_granularity thing??? - Could use different copyscreentoscreen function for the pageflip copies - (which would use different src and dst offsets) to avoid this. */ - if (info->allowColorTiling && !info->noBackBuffer) { - info->textureSize = info->FbMapSize - ((info->FbMapSize - info->textureSize + - width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes * 16); - } - if (info->textureSize > 0) { - l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - - /* Round the texture size up to the nearest whole number of - * texture regions. Again, be greedy about this, don't - * round down. - */ - info->log2TexGran = l; - info->textureSize = (info->textureSize >> l) << l; - } else { - info->textureSize = 0; - } - - /* Set a minimum usable local texture heap size. This will fit - * two 256x256x32bpp textures. - */ - if (info->textureSize < 512 * 1024) { - info->textureOffset = 0; - info->textureSize = 0; - } - - if (info->allowColorTiling && !info->noBackBuffer) { - info->textureOffset = ((info->FbMapSize - info->textureSize) / - (width_bytes * 16)) * (width_bytes * 16); - } - else { - /* Reserve space for textures */ - info->textureOffset = ((info->FbMapSize - info->textureSize + - RADEON_BUFFER_ALIGN) & - ~(CARD32)RADEON_BUFFER_ALIGN); - } - - /* Reserve space for the shared depth - * buffer. - */ - info->depthOffset = ((info->textureOffset - depthSize + - RADEON_BUFFER_ALIGN) & - ~(CARD32)RADEON_BUFFER_ALIGN); - - /* Reserve space for the shared back buffer */ - if (info->noBackBuffer) { - info->backOffset = info->depthOffset; - } else { - info->backOffset = ((info->depthOffset - bufferSize + - RADEON_BUFFER_ALIGN) & - ~(CARD32)RADEON_BUFFER_ALIGN); - } - - info->backY = info->backOffset / width_bytes; - info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp; - - scanlines = info->FbMapSize / width_bytes; - if (scanlines > 8191) scanlines = 8191; - - MemBox.x1 = 0; - MemBox.y1 = 0; - MemBox.x2 = pScrn->displayWidth; - MemBox.y2 = scanlines; - - if (!xf86InitFBManager(pScreen, &MemBox)) { - xf86DrvMsg(scrnIndex, X_ERROR, - "Memory manager initialization to " - "(%d,%d) (%d,%d) failed\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - return FALSE; - } else { - int width, height; - - xf86DrvMsg(scrnIndex, X_INFO, - "Memory manager initialized to (%d,%d) (%d,%d)\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - /* why oh why can't we just request modes which are guaranteed to be 16 lines - aligned... sigh */ - if ((fbarea = xf86AllocateOffscreenArea(pScreen, - pScrn->displayWidth, - info->allowColorTiling ? - ((pScrn->virtualY + 15) & ~15) - - pScrn->virtualY + 2 : 2, - 0, NULL, NULL, - NULL))) { - xf86DrvMsg(scrnIndex, X_INFO, - "Reserved area from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); - } else { - xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); - } - - RADEONDRIAllocatePCIGARTTable(pScreen); - - if (xf86QueryLargestOffscreenArea(pScreen, &width, - &height, 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); - - /* Lines in offscreen area needed for depth buffer and - * textures - */ - info->depthTexLines = (scanlines - - info->depthOffset / width_bytes); - info->backLines = (scanlines - - info->backOffset / width_bytes - - info->depthTexLines); - info->backArea = NULL; - } else { - xf86DrvMsg(scrnIndex, X_ERROR, - "Unable to determine largest offscreen area " - "available\n"); - return FALSE; - } - } - - xf86DrvMsg(scrnIndex, X_INFO, - "Will use back buffer at offset 0x%x\n", - info->backOffset); - xf86DrvMsg(scrnIndex, X_INFO, - "Will use depth buffer at offset 0x%x\n", - info->depthOffset); - xf86DrvMsg(scrnIndex, X_INFO, - "Will use %d kb for PCI GART table at offset 0x%x\n", - info->pciGartSize/1024, info->pciGartOffset); - xf86DrvMsg(scrnIndex, X_INFO, - "Will use %d kb for textures at offset 0x%x\n", - info->textureSize/1024, info->textureOffset); - - info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | - ((info->frontOffset + info->fbLocation) >> 10)); - - info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | - ((info->backOffset + info->fbLocation) >> 10)); +#ifdef USE_EXA + if (info->useEXA && !RADEONSetupMemEXA(pScreen)) + return FALSE; +#endif - info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | - ((info->depthOffset + info->fbLocation) >> 10)); - } else +#if defined(XF86DRI) && defined(USE_XAA) + if (!info->useEXA && hasDRI && !RADEONSetupMemXAA_DRI(scrnIndex, pScreen)) + return FALSE; #endif - { - int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; - MemBox.x1 = 0; - MemBox.y1 = 0; - MemBox.x2 = pScrn->displayWidth; - y2 = info->FbMapSize / width_bytes; - if (y2 >= 32768) y2 = 32767; /* because MemBox.y2 is signed short */ - MemBox.y2 = y2; - - /* The acceleration engine uses 14 bit - signed coordinates, so we can't have any - drawable caches beyond this region. */ - if (MemBox.y2 > 8191) MemBox.y2 = 8191; - - if (!xf86InitFBManager(pScreen, &MemBox)) { - xf86DrvMsg(scrnIndex, X_ERROR, - "Memory manager initialization to " - "(%d,%d) (%d,%d) failed\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - return FALSE; - } else { - int width, height; - FBAreaPtr fbarea; - xf86DrvMsg(scrnIndex, X_INFO, - "Memory manager initialized to (%d,%d) (%d,%d)\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - if ((fbarea = xf86AllocateOffscreenArea(pScreen, - pScrn->displayWidth, - info->allowColorTiling ? - ((pScrn->virtualY + 15) & ~15) - - pScrn->virtualY + 2 : 2, - 0, NULL, NULL, - NULL))) { - xf86DrvMsg(scrnIndex, X_INFO, - "Reserved area from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); - } else { - xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); - } - if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, - 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); - } - } - } +#ifdef USE_XAA + if (!info->useEXA && !hasDRI && !RADEONSetupMemXAA(scrnIndex, pScreen)) + return FALSE; +#endif - info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) << 22) | - ((info->fbLocation + pScrn->fbOffset) >> 10)); + info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) + << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10)); - /* Acceleration setup */ + /* Acceleration setup */ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { if (RADEONAccelInit(pScreen)) { xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); @@ -5538,41 +5659,53 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->accelOn = FALSE; } - /* DGA setup */ - RADEONDGAInit(pScreen); + /* DGA setup XXX FIXME EXA */ + if (!info->useEXA) + RADEONDGAInit(pScreen); - /* Backing store setup */ + /* Backing store setup */ miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); - /* Set Silken Mouse */ + /* Set Silken Mouse */ xf86SetSilkenMouse(pScreen); - /* Cursor setup */ + /* Cursor setup */ miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); - /* Hardware cursor setup */ + /* Hardware cursor setup */ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { if (RADEONCursorInit(pScreen)) { - int width, height; +#ifdef USE_EXA + if (info->useEXA) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using hardware cursor (offset %d)\n", + info->cursor_offset); + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + int width, height; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursor (scanline %ld)\n", - info->cursor_start / pScrn->displayWidth - / info->CurrentLayout.pixel_bytes); - if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using hardware cursor (scanline %ld)\n", + info->cursor_offset / pScrn->displayWidth + / info->CurrentLayout.pixel_bytes); + if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + } } +#endif /* USE_XAA */ } else { xf86DrvMsg(scrnIndex, X_ERROR, "Hardware cursor initialization failed\n"); xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); } } else { - info->cursor_start = 0; + info->cursor_offset = 0; xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); } @@ -5634,7 +5767,15 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, done their thing, complete the DRI setup. */ if (!(info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen))) { - RADEONAccelInitMMIO(pScreen, info->accel); +#ifdef USE_EXA + if (info->useEXA) { + RADEONDrawInitMMIO(pScreen); + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) + RADEONAccelInitMMIO(pScreen, info->accel); +#endif /* USE_XAA */ } } if (info->directRenderingEnabled) { @@ -7992,7 +8133,8 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) #endif } - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn) + RADEON_SYNC(info, pScrn); if (info->FBDev) { RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); @@ -8015,7 +8157,7 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } if (info->accelOn) { - info->accel->Sync(pScrn); + RADEON_SYNC(info, pScrn); RADEONEngineRestore(pScrn); } @@ -8185,7 +8327,8 @@ _X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) if (info->CPStarted) DRILock(pScrn->pScreen, 0); #endif - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn) + RADEON_SYNC(info, pScrn); if(info->MergedFB) { RADEONAdjustFrameMerged(scrnIndex, x, y, flags); @@ -8312,10 +8455,12 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) } #endif - if(info->RenderTex) { +#ifdef USE_XAA + if(!info->useEXA && info->RenderTex) { xf86FreeOffscreenLinear(info->RenderTex); info->RenderTex = NULL; } +#endif /* USE_XAA */ if (pScrn->vtSema) { RADEONDisplayPowerManagementSet(pScrn, DPMSModeOn, 0); @@ -8323,11 +8468,21 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) } RADEONUnmapMem(pScrn); - if (info->accel) XAADestroyInfoRec(info->accel); - info->accel = NULL; +#ifdef USE_EXA + if (info->useEXA && info->accelOn) + exaDriverFini(pScreen); +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + if (info->accel) + XAADestroyInfoRec(info->accel); + info->accel = NULL; - if (info->scratch_save) xfree(info->scratch_save); - info->scratch_save = NULL; + if (info->scratch_save) + xfree(info->scratch_save); + info->scratch_save = NULL; + } +#endif /* USE_XAA */ if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); info->cursor = NULL; @@ -8476,7 +8631,8 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (info->CPStarted) DRILock(pScrn->pScreen, 0); #endif - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn) + RADEON_SYNC(info, pScrn); if (info->FBDev) { fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); diff --git a/src/radeon_exa.c b/src/radeon_exa.c new file mode 100644 index 0000000..632faaf --- /dev/null +++ b/src/radeon_exa.c @@ -0,0 +1,463 @@ +/* + * Copyright 2005 Eric Anholt + * Copyright 2005 Benjamin Herrenschmidt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt <anholt@FreeBSD.org> + * Zack Rusin <zrusin@trolltech.com> + * Benjamin Herrenschmidt <benh@kernel.crashing.org> + * + */ + +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_dri.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_sarea.h" + +#include "xf86.h" + + +/***********************************************************************/ +#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86Screens[pScr->myNum]; \ + RADEONInfoPtr info = RADEONPTR(pScrn) + +#define RADEON_TRACE_FALL 0 +#define RADEON_TRACE_DRAW 0 + +#if RADEON_TRACE_FALL +#define RADEON_FALLBACK(x) \ +do { \ + ErrorF("%s: ", __FUNCTION__); \ + ErrorF x; \ + return FALSE; \ +} while (0) +#else +#define RADEON_FALLBACK(x) return FALSE +#endif + +#if RADEON_TRACE_DRAW +#define TRACE do { ErrorF("TRACE: %s\n", __FUNCTION__); } while(0) +#else +#define TRACE +#endif + +static struct { + int rop; + int pattern; +} RADEON_ROP[] = { + { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */ + { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */ + { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */ + { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */ + { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */ + { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */ + { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */ + { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */ + { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */ + { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */ + { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */ + { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */ + { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */ + { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */ + { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */ + { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ +}; + +/* Compute log base 2 of val. */ +static __inline__ int +RADEONLog2(int val) +{ + int bits; + + for (bits = 0; val != 0; val >>= 1, ++bits) + ; + return bits - 1; +} + +static __inline__ CARD32 F_TO_DW(float val) +{ + union { + float f; + CARD32 l; + } tmp; + tmp.f = val; + return tmp.l; +} + +/* 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) +{ + switch (bpp) { + case 8: + *type = ATI_DATATYPE_CI8; + return TRUE; + case 16: + *type = ATI_DATATYPE_RGB565; + return TRUE; + case 24: + *type = ATI_DATATYPE_CI8; + return TRUE; + case 32: + *type = ATI_DATATYPE_ARGB8888; + return TRUE; + default: + RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp)); + return FALSE; + } +} + +static Bool RADEONPixmapIsColortiled(PixmapPtr pPix) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + + /* This doesn't account for the back buffer, which we may want to wrap in + * a pixmap at some point for the purposes of DRI buffer moves. + */ + if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0) + return TRUE; + else + return FALSE; +} + +static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, CARD32 *pitch_offset, + unsigned int offset, unsigned int pitch) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + + if (pitch % info->exa.card.pixmapPitchAlign != 0) + RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch)); + + if (offset % info->exa.card.pixmapOffsetAlign != 0) + RADEON_FALLBACK(("Bad offset 0x%08x\n", offset)); + + pitch = pitch >> 6; + *pitch_offset = (pitch << 22) | (offset >> 10); + + /* If it's the front buffer, we've got to note that it's tiled? */ + if (RADEONPixmapIsColortiled(pPix)) + *pitch_offset |= RADEON_DST_TILE_MACRO; + return TRUE; +} + +static Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + CARD32 pitch, offset; + int bpp; + + bpp = pPix->drawable.bitsPerPixel; + if (bpp == 24) + bpp = 8; + + offset = exaGetPixmapOffset(pPix) + info->fbLocation; + pitch = exaGetPixmapPitch(pPix); + + return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); +} + +#if X_BYTE_ORDER == X_BIG_ENDIAN + +static unsigned long swapper_surfaces[3]; + +static Bool RADEONPrepareAccess(PixmapPtr pPix, int index) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 offset = exaGetPixmapOffset(pPix); + int bpp, rc, soff; + CARD32 size, flags; + + /* Front buffer is always set with proper swappers */ + if (offset == 0) + return TRUE; + + /* If same bpp as front buffer, just do nothing as the main + * swappers will apply + */ + bpp = pPix->drawable.bitsPerPixel; + if (bpp == pScrn->bitsPerPixel) + return TRUE; + + /* We need to setup a separate swapper, let's request a + * surface. We need to align the size first + */ + size = exaGetPixmapSize(pPix); + size = (size + RADEON_BUFFER_ALIGN) & ~(RADEON_BUFFER_ALIGN); + + /* Set surface to tiling disabled with appropriate swapper */ + switch (bpp) { + case 16: + flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; + break; + case 32: + flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; + break; + default: + flags = 0; + } +#if defined(XF86DRI) + if (info->directRenderingEnabled && info->allowColorTiling) { + drmRadeonSurfaceAlloc drmsurfalloc; + + drmsurfalloc.address = offset; + drmsurfalloc.size = size; + drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */ + + rc = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, + &drmsurfalloc, sizeof(drmsurfalloc)); + if (rc < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm: could not allocate surface for access" + " swapper, err: %d!\n", rc); + return FALSE; + } + swapper_surfaces[index] = offset; + + return TRUE; + } +#endif + soff = (index + 1) * 0x10; + OUTREG(RADEON_SURFACE0_INFO + soff, flags); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); + swapper_surfaces[index] = offset; + return TRUE; +} + +static void RADEONFinishAccess(PixmapPtr pPix, int index) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 offset = exaGetPixmapOffset(pPix); + int bpp, soff; + + /* Front buffer is always set with proper swappers */ + if (offset == 0) + return; + + if (swapper_surfaces[index] == 0) + return; +#if defined(XF86DRI) + if (info->directRenderingEnabled && info->allowColorTiling) { + drmRadeonSurfaceFree drmsurffree; + + drmsurffree.address = offset; + drmCommandWrite(info->drmFD, DRM_RADEON_SURF_FREE, + &drmsurffree, sizeof(drmsurffree)); + swapper_surfaces[index] = 0; + return; + } +#endif + soff = (index + 1) * 0x10; + OUTREG(RADEON_SURFACE0_INFO + soff, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); + swapper_surfaces[index] = 0; +} + +#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ + +#define RADEON_SWITCH_TO_2D() \ +do { \ + if (info->engineMode == EXA_ENGINEMODE_2D) \ + break; \ + BEGIN_ACCEL(2); \ + OUT_ACCEL_REG(RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH); \ + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, \ + RADEON_WAIT_HOST_IDLECLEAN | \ + RADEON_WAIT_3D_IDLECLEAN); \ + FINISH_ACCEL(); \ + info->engineMode = EXA_ENGINEMODE_2D; \ +} while (0); + +#define RADEON_SWITCH_TO_3D() \ +do { \ + if (info->engineMode == EXA_ENGINEMODE_3D) \ + break; \ + BEGIN_ACCEL(2); \ + OUT_ACCEL_REG(RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH); \ + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, \ + RADEON_WAIT_HOST_IDLECLEAN | \ + RADEON_WAIT_2D_IDLECLEAN | \ + RADEON_WAIT_3D_IDLECLEAN); \ + FINISH_ACCEL(); \ + info->engineMode = EXA_ENGINEMODE_3D; \ +} while (0); + +#define ENTER_DRAW(x) TRACE +#define LEAVE_DRAW(x) TRACE +/***********************************************************************/ + +#define ACCEL_MMIO +#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO +#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) +#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) +#define FINISH_ACCEL() + +#ifdef RENDER +#include "radeon_exa_render.c" +#endif +#include "radeon_exa_funcs.c" + +#undef ACCEL_MMIO +#undef ACCEL_PREAMBLE +#undef BEGIN_ACCEL +#undef OUT_ACCEL_REG +#undef FINISH_ACCEL + +#ifdef XF86DRI + +#define ACCEL_CP +#define ACCEL_PREAMBLE() \ + RING_LOCALS; \ + RADEONCP_REFRESH(pScrn, info) +#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) +#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) +#define FINISH_ACCEL() ADVANCE_RING() + +#define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) + +#ifdef RENDER +#include "radeon_exa_render.c" +#endif +#include "radeon_exa_funcs.c" + +#endif /* XF86DRI */ + +/* + * Once screen->off_screen_base is set, this function + * allocates the remaining memory appropriately + */ +Bool RADEONSetupMemEXA (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + int l; + int next, screen_size; + int byteStride = pScrn->displayWidth * cpp; + + /* Need to adjust screen size for 16 line tiles, and then make it align to. + * the buffer alignment requirement. + */ + if (info->allowColorTiling) + screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; + else + screen_size = pScrn->virtualY * byteStride; + + info->exa.card.memoryBase = info->FB + pScrn->fbOffset; + info->exa.card.memorySize = info->FbMapSize; + info->exa.card.offScreenBase = screen_size; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", + info->exa.card.memorySize / 1024); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for front buffer at offset 0x%08x\n", + screen_size / 1024, 0); + +#if defined(XF86DRI) + if (info->directRenderingEnabled) { + int depth_size; + + info->frontOffset = 0; + info->frontPitch = pScrn->displayWidth; + + if (info->IsPCI && info->drmMinor >= 19) { + info->pciGartSize = RADEON_PCIGART_TABLE_SIZE; + info->pciGartOffset = RADEON_ALIGN(info->exa.card.offScreenBase, + 256); + info->exa.card.offScreenBase = info->pciGartOffset + + info->pciGartSize; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for PCI GART at offset 0x%08x\n", + RADEON_PCIGART_TABLE_SIZE / 1024, + (int)info->pciGartOffset); + } + /* Reserve a static area for the back buffer the same size as the + * visible screen. XXX: This would be better initialized in ati_dri.c + * when GLX is set up, but the offscreen memory manager's allocations + * don't last through VT switches, while the kernel's understanding of + * offscreen locations does. + */ + info->backPitch = pScrn->displayWidth; + next = RADEON_ALIGN(info->exa.card.offScreenBase, RADEON_BUFFER_ALIGN); + if (!info->noBackBuffer && + next + screen_size <= info->exa.card.memorySize) + { + info->backOffset = next; + info->exa.card.offScreenBase = next + screen_size; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for back buffer at offset 0x%08x\n", + screen_size / 1024, info->backOffset); + } + + /* Reserve the static depth buffer, and adjust pitch and height to + * handle tiling. + */ + info->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); + depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * cpp; + next = RADEON_ALIGN(info->exa.card.offScreenBase, RADEON_BUFFER_ALIGN); + if (next + depth_size <= info->exa.card.memorySize) + { + info->depthOffset = next; + info->exa.card.offScreenBase = next + depth_size; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for depth buffer at offset 0x%08x\n", + depth_size / 1024, info->depthOffset); + } + + /* Reserve approx. half of remaining offscreen memory for local + * textures. Round down to a whole number of texture regions. + */ + info->textureSize = (info->exa.card.memorySize - + info->exa.card.offScreenBase) / 2; + l = RADEONLog2(info->textureSize / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) + l = RADEON_LOG_TEX_GRANULARITY; + info->textureSize = (info->textureSize >> l) << l; + if (info->textureSize >= 512 * 1024) { + info->textureOffset = info->exa.card.offScreenBase; + info->exa.card.offScreenBase += info->textureSize; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for textures at offset 0x%08x\n", + info->textureSize / 1024, info->textureOffset); + } else { + /* Minimum texture size is for 2 256x256x32bpp textures */ + info->textureSize = 0; + } + } +#endif /* XF86DRI */ + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", + (info->exa.card.memorySize - info->exa.card.offScreenBase) / + 1024, info->exa.card.offScreenBase); + + return TRUE; +} diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c new file mode 100644 index 0000000..b601283 --- /dev/null +++ b/src/radeon_exa_funcs.c @@ -0,0 +1,408 @@ +/* + * Copyright 2005 Eric Anholt + * Copyright 2005 Benjamin Herrenschmidt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt <anholt@FreeBSD.org> + * Zack Rusin <zrusin@trolltech.com> + * Benjamin Herrenschmidt <benh@kernel.crashing.org> + * + */ + +#if defined(ACCEL_MMIO) && defined(ACCEL_CP) +#error Cannot define both MMIO and CP acceleration! +#endif + +#if !defined(UNIXCPP) || defined(ANSICPP) +#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix +#else +#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix +#endif + +#ifdef ACCEL_MMIO +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO) +#else +#ifdef ACCEL_CP +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP) +#else +#error No accel type defined! +#endif +#endif + +#include "radeon.h" +#include "atidri.h" + +#include "exa.h" + +#include "fbdevhw.h" + +static void +FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) +{ + TRACE; + + FUNC_NAME(RADEONWaitForIdle)(xf86Screens[pScreen->myNum]); +} + +static Bool +FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + CARD32 datatype, dst_pitch_offset; + ACCEL_PREAMBLE(); + + TRACE; + + if (pPix->drawable.bitsPerPixel == 24) + RADEON_FALLBACK(("24bpp unsupported\n")); + if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype)) + RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); + if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset)) + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch 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_BRUSH_SOLID_COLOR | + (datatype << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP[alu].pattern | + RADEON_GMC_CLR_CMP_CNTL_DIS); + OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); + OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, pm); + OUT_ACCEL_REG(RADEON_DP_CNTL, + (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); + FINISH_ACCEL(); + + return TRUE; +} + + +static void +FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2) +{ + + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + ACCEL_PREAMBLE(); + + TRACE; + + BEGIN_ACCEL(2); + OUT_ACCEL_REG(RADEON_DST_Y_X, (y1 << 16) | x1); + OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1)); + FINISH_ACCEL(); +} + +static void +FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPix) +{ + TRACE; +} + +static Bool +FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, + int xdir, int ydir, + int rop, + Pixel planemask) +{ + RINFO_FROM_SCREEN(pDst->drawable.pScreen); + CARD32 datatype, src_pitch_offset, dst_pitch_offset; + ACCEL_PREAMBLE(); + + TRACE; + + info->xdir = xdir; + info->ydir = ydir; + + if (pDst->drawable.bitsPerPixel == 24) + RADEON_FALLBACK(("24bpp unsupported")); + if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype)) + RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); + if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset)) + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); + 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(); + + return TRUE; +} + +static void +FUNC_NAME(RADEONCopy)(PixmapPtr pDst, + int srcX, int srcY, + int dstX, int dstY, + int w, int h) +{ + + RINFO_FROM_SCREEN(pDst->drawable.pScreen); + ACCEL_PREAMBLE(); + + TRACE; + + if (info->xdir < 0) { + srcX += w - 1; + dstX += w - 1; + } + if (info->ydir < 0) { + srcY += h - 1; + dstY += h - 1; + } + + BEGIN_ACCEL(3); + + OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); + OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); + OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); + + FINISH_ACCEL(); +} + +static void +FUNC_NAME(RADEONDoneCopy)(PixmapPtr pDst) +{ + TRACE; +} + +static Bool +FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, char *src, int src_pitch) +{ +#if X_BYTE_ORDER == X_BIG_ENDIAN || defined(ACCEL_CP) + RINFO_FROM_SCREEN(pDst->drawable.pScreen); +#endif + CARD8 *dst = pDst->devPrivate.ptr; + unsigned int dst_pitch = exaGetPixmapPitch(pDst); + unsigned int w = pDst->drawable.width; + unsigned int h = pDst->drawable.height; + unsigned int bpp = pDst->drawable.bitsPerPixel; +#ifdef ACCEL_CP + unsigned int hpass; + CARD32 buf_pitch; +#endif +#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 | + RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP); +#endif + + TRACE; + +#ifdef ACCEL_CP + if (info->directRenderingEnabled) { + CARD8 *buf; + int cpp = bpp / 8; + ACCEL_PREAMBLE(); + + RADEON_SWITCH_TO_2D(); + while ((buf = RADEONHostDataBlit(pScrn, + cpp, w, dst_pitch, &buf_pitch, + &dst, &h, &hpass)) != 0) { + RADEONHostDataBlitCopyPass(pScrn, cpp, buf, (unsigned char *)src, + hpass, buf_pitch, src_pitch); + src += hpass * src_pitch; + } + + exaMarkSync(pDst->drawable.pScreen); + return TRUE; + } +#endif + + /* Do we need that sync here ? probably not .... */ + exaWaitSync(pDst->drawable.pScreen); + +#if X_BYTE_ORDER == X_BIG_ENDIAN + switch(bpp) { + case 15: + case 16: + swapper |= RADEON_NONSURF_AP0_SWP_16BPP + | RADEON_NONSURF_AP1_SWP_16BPP; + break; + case 24: + case 32: + swapper |= RADEON_NONSURF_AP0_SWP_32BPP + | RADEON_NONSURF_AP1_SWP_32BPP; + break; + } + OUTREG(RADEON_SURFACE_CNTL, swapper); +#endif + w *= bpp / 8; + + while (h--) { + memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* restore byte swapping */ + OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); +#endif + + return TRUE; +} + +static Bool +FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) +{ +#if X_BYTE_ORDER == X_BIG_ENDIAN + RINFO_FROM_SCREEN(pSrc->drawable.pScreen); + unsigned char *RADEONMMIO = info->MMIO; + unsigned int swapper = info->ModeReg.surface_cntl & + ~(RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP | + RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP); +#endif + unsigned char *src = pSrc->devPrivate.ptr; + int src_pitch = exaGetPixmapPitch(pSrc); + int bpp = pSrc->drawable.bitsPerPixel; + + TRACE; + + /* + * This is currently done without DMA until I have ironed out the + * various endian issues with R300 among others + */ + exaWaitSync(pSrc->drawable.pScreen); + +#if X_BYTE_ORDER == X_BIG_ENDIAN + switch(bpp) { + case 15: + case 16: + swapper |= RADEON_NONSURF_AP0_SWP_16BPP + | RADEON_NONSURF_AP1_SWP_16BPP; + break; + case 24: + case 32: + swapper |= RADEON_NONSURF_AP0_SWP_32BPP + | RADEON_NONSURF_AP1_SWP_32BPP; + break; + } + OUTREG(RADEON_SURFACE_CNTL, swapper); +#endif + + src += (x * bpp / 8) + (y * src_pitch); + w *= bpp / 8; + + while (h--) { + memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* restore byte swapping */ + OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); +#endif + + return TRUE; +} + +Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) +{ + RINFO_FROM_SCREEN(pScreen); + + memset(&info->exa.accel, 0, sizeof(ExaAccelInfoRec)); + + info->exa.accel.PrepareSolid = FUNC_NAME(RADEONPrepareSolid); + info->exa.accel.Solid = FUNC_NAME(RADEONSolid); + info->exa.accel.DoneSolid = FUNC_NAME(RADEONDoneSolid); + + info->exa.accel.PrepareCopy = FUNC_NAME(RADEONPrepareCopy); + info->exa.accel.Copy = FUNC_NAME(RADEONCopy); + info->exa.accel.DoneCopy = FUNC_NAME(RADEONDoneCopy); + + info->exa.accel.WaitMarker = FUNC_NAME(RADEONSync); + info->exa.accel.UploadToScreen = FUNC_NAME(RADEONUploadToScreen); + info->exa.accel.DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); + +#if X_BYTE_ORDER == X_BIG_ENDIAN + info->exa.accel.PrepareAccess = RADEONPrepareAccess; + info->exa.accel.FinishAccess = RADEONFinishAccess; +#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ + + info->exa.card.flags = EXA_OFFSCREEN_PIXMAPS; + info->exa.card.pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1; + info->exa.card.pixmapPitchAlign = 64; + + info->exa.card.maxX = 2047; + info->exa.card.maxY = 2047; + + if (info->RenderAccel) { + if (info->ChipFamily >= CHIP_FAMILY_R300) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " + "unsupported on R300 type cards and newer.\n"); + } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) || + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_R200)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " + "enabled for R200 type cards.\n"); + info->exa.accel.CheckComposite = R200CheckComposite; + info->exa.accel.PrepareComposite = + FUNC_NAME(R200PrepareComposite); + info->exa.accel.Composite = FUNC_NAME(RadeonComposite); + info->exa.accel.DoneComposite = RadeonDoneComposite; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " + "enabled for R100 type cards.\n"); + info->exa.accel.CheckComposite = R100CheckComposite; + info->exa.accel.PrepareComposite = + FUNC_NAME(R100PrepareComposite); + info->exa.accel.Composite = FUNC_NAME(RadeonComposite); + info->exa.accel.DoneComposite = RadeonDoneComposite; + } + } + + RADEONEngineInit(pScrn); + + if (!exaDriverInit(pScreen, &info->exa)) { + return FALSE; + } + exaMarkSync(pScreen); + + return TRUE; +} + +#undef FUNC_NAME diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c new file mode 100644 index 0000000..d4beb87 --- /dev/null +++ b/src/radeon_exa_render.c @@ -0,0 +1,799 @@ +/* + * Copyright 2005 Eric Anholt + * Copyright 2005 Benjamin Herrenschmidt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt <anholt@FreeBSD.org> + * Zack Rusin <zrusin@trolltech.com> + * Benjamin Herrenschmidt <benh@kernel.crashing.org> + * + */ + +#if defined(ACCEL_MMIO) && defined(ACCEL_CP) +#error Cannot define both MMIO and CP acceleration! +#endif + +#if !defined(UNIXCPP) || defined(ANSICPP) +#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix +#else +#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix +#endif + +#ifdef ACCEL_MMIO +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO) +#else +#ifdef ACCEL_CP +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP) +#else +#error No accel type defined! +#endif +#endif + +#ifndef ACCEL_CP +#define ONLY_ONCE +#endif + +/* Only include the following (generic) bits once. */ +#ifdef ONLY_ONCE +static Bool is_transform[2]; +static PictTransform *transform[2]; + +struct blendinfo { + Bool dst_alpha; + Bool src_alpha; + CARD32 blend_cntl; +}; + +static struct blendinfo RadeonBlendOp[] = { + /* Clear */ + {0, 0, RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ZERO}, + /* Src */ + {0, 0, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO}, + /* Dst */ + {0, 0, RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ONE}, + /* Over */ + {0, 1, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA}, + /* OverReverse */ + {1, 0, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_ONE}, + /* In */ + {1, 0, RADEON_SRC_BLEND_GL_DST_ALPHA | RADEON_DST_BLEND_GL_ZERO}, + /* InReverse */ + {0, 1, RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_SRC_ALPHA}, + /* Out */ + {1, 0, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_ZERO}, + /* OutReverse */ + {0, 1, RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA}, + /* Atop */ + {1, 1, RADEON_SRC_BLEND_GL_DST_ALPHA | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA}, + /* AtopReverse */ + {1, 1, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_SRC_ALPHA}, + /* Xor */ + {1, 1, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA}, + /* Add */ + {0, 0, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ONE}, +}; + +struct formatinfo { + int fmt; + Bool byte_swap; + CARD32 card_fmt; +}; + +/* Note on texture formats: + * TXFORMAT_Y8 expands to (Y,Y,Y,1). TXFORMAT_I8 expands to (I,I,I,I) + */ +static struct formatinfo R100TexFormats[] = { + {PICT_a8r8g8b8, 0, RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x8r8g8b8, 0, RADEON_TXFORMAT_ARGB8888}, + {PICT_a8b8g8r8, 1, RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x8b8g8r8, 1, RADEON_TXFORMAT_RGBA8888}, + {PICT_r5g6b5, 0, RADEON_TXFORMAT_RGB565}, + {PICT_a1r5g5b5, 0, RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x1r5g5b5, 0, RADEON_TXFORMAT_ARGB1555}, + {PICT_a8, 0, RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP}, +}; + +static struct formatinfo R200TexFormats[] = { + {PICT_a8r8g8b8, 0, R200_TXFORMAT_ARGB8888 | R200_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x8r8g8b8, 0, R200_TXFORMAT_ARGB8888}, + {PICT_a8r8g8b8, 1, R200_TXFORMAT_RGBA8888 | R200_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x8r8g8b8, 1, R200_TXFORMAT_RGBA8888}, + {PICT_r5g6b5, 0, R200_TXFORMAT_RGB565}, + {PICT_a1r5g5b5, 0, R200_TXFORMAT_ARGB1555 | R200_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x1r5g5b5, 0, R200_TXFORMAT_ARGB1555}, + {PICT_a8, 0, R200_TXFORMAT_I8 | R200_TXFORMAT_ALPHA_IN_MAP}, +}; + +/* Common Radeon setup code */ + +static Bool RADEONGetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format) +{ + switch (pDstPicture->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + *dst_format = RADEON_COLOR_FORMAT_ARGB8888; + break; + case PICT_r5g6b5: + *dst_format = RADEON_COLOR_FORMAT_RGB565; + break; + case PICT_a1r5g5b5: + case PICT_x1r5g5b5: + *dst_format = RADEON_COLOR_FORMAT_ARGB1555; + break; + case PICT_a8: + *dst_format = RADEON_COLOR_FORMAT_RGB8; + break; + default: + RADEON_FALLBACK(("Unsupported dest format 0x%x\n", + (int)pDstPicture->format)); + } + + return TRUE; +} +static CARD32 RADEONGetBlendCntl(int op, CARD32 dst_format) +{ + CARD32 blendcntl = RadeonBlendOp[op].blend_cntl; + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (PICT_FORMAT_A(dst_format) == 0 && RadeonBlendOp[op].dst_alpha) { + if ((blendcntl & RADEON_SRC_BLEND_MASK) == + RADEON_SRC_BLEND_GL_DST_ALPHA) { + blendcntl = (blendcntl & ~RADEON_SRC_BLEND_MASK) | + RADEON_SRC_BLEND_GL_ONE; + } else if ((blendcntl & RADEON_SRC_BLEND_MASK) == + RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA) { + blendcntl = (blendcntl & ~RADEON_SRC_BLEND_MASK) | + RADEON_SRC_BLEND_GL_ZERO; + } + } + + return blendcntl; +} + +union intfloat { + float f; + CARD32 i; +}; + +/* R100-specific code */ + +static Bool R100CheckCompositeTexture(PicturePtr pPict, int unit) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + + if ((w > 0x7ff) || (h > 0x7ff)) + RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); + + for (i = 0; i < sizeof(R100TexFormats) / sizeof(R100TexFormats[0]); i++) { + if (R100TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(R100TexFormats) / sizeof(R100TexFormats[0])) + RADEON_FALLBACK(("Unsupported picture format 0x%x\n", + (int)pPict->format)); + + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) + RADEON_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h)); + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) + { + RADEON_FALLBACK(("Unsupported filter 0x%x\n", pPict->filter)); + } + + return TRUE; +} + +#endif /* ONLY_ONCE */ + +static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix, + int unit) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + CARD32 txfilter, txformat, txoffset, txpitch; + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + ACCEL_PREAMBLE(); + + txpitch = exaGetPixmapPitch(pPix); + txoffset = exaGetPixmapOffset(pPix) + info->fbLocation; + + for (i = 0; i < sizeof(R100TexFormats) / sizeof(R100TexFormats[0]); i++) + { + if (R100TexFormats[i].fmt == pPict->format) + break; + } + txformat = R100TexFormats[i].card_fmt; + if (R100TexFormats[i].byte_swap) + txoffset |= RADEON_TXO_ENDIAN_BYTE_SWAP; + if (RADEONPixmapIsColortiled(pPix)) + txoffset |= RADEON_TXO_MACRO_TILE; + + if (pPict->repeat) { + txformat |= RADEONLog2(w) << RADEON_TXFORMAT_WIDTH_SHIFT; + txformat |= RADEONLog2(h) << RADEON_TXFORMAT_HEIGHT_SHIFT; + } else + txformat |= RADEON_TXFORMAT_NON_POWER2; + txformat |= unit << 24; /* RADEON_TXFORMAT_ST_ROUTE_STQX */ + + if ((txoffset & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + if ((txpitch & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch)); + + switch (pPict->filter) { + case PictFilterNearest: + txfilter = (RADEON_MAG_FILTER_NEAREST | RADEON_MIN_FILTER_NEAREST); + break; + case PictFilterBilinear: + txfilter = (RADEON_MAG_FILTER_LINEAR | RADEON_MIN_FILTER_LINEAR); + break; + default: + RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter)); + } + + BEGIN_ACCEL(5); + if (unit == 0) { + OUT_ACCEL_REG(RADEON_PP_TXFILTER_0, txfilter); + OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat); + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset); + OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_0, + (pPix->drawable.width - 1) | + ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); + OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_0, txpitch - 32); + } else { + OUT_ACCEL_REG(RADEON_PP_TXFILTER_1, txfilter); + OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat); + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset); + OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_1, + (pPix->drawable.width - 1) | + ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); + OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_1, txpitch - 32); + } + FINISH_ACCEL(); + + if (pPict->transform != 0) { + is_transform[unit] = TRUE; + transform[unit] = pPict->transform; + } else { + is_transform[unit] = FALSE; + } + + return TRUE; +} + +#ifdef ONLY_ONCE +static Bool R100CheckComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture) +{ + CARD32 tmp1; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0])) + RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op)); + if (pMaskPicture != NULL && pMaskPicture->componentAlpha && + RadeonBlendOp[op].src_alpha) + { + RADEON_FALLBACK(("Component alpha not supported with source " + "alpha blending.\n")); + } + if (pDstPicture->pDrawable->width >= (1 << 11) || + pDstPicture->pDrawable->height >= (1 << 11)) + { + RADEON_FALLBACK(("Dest w/h too large (%d,%d).\n", + pDstPicture->pDrawable->width, + pDstPicture->pDrawable->height)); + } + + if (!R100CheckCompositeTexture(pSrcPicture, 0)) + return FALSE; + if (pMaskPicture != NULL && !R100CheckCompositeTexture(pMaskPicture, 1)) + return FALSE; + + if (pDstPicture->componentAlpha) + return FALSE; + + if (!RADEONGetDestFormat(pDstPicture, &tmp1)) + return FALSE; + + return TRUE; +} +#endif /* ONLY_ONCE */ + +static Bool FUNC_NAME(R100PrepareComposite)(int op, + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture, + PixmapPtr pSrc, + PixmapPtr pMask, + PixmapPtr pDst) +{ + RINFO_FROM_SCREEN(pDst->drawable.pScreen); + CARD32 dst_format, dst_offset, dst_pitch, colorpitch; + CARD32 pp_cntl, blendcntl, cblend, ablend; + int pixel_shift; + ACCEL_PREAMBLE(); + + TRACE; + + if (!info->XInited3D) + RADEONInit3DEngine(pScrn); + + RADEONGetDestFormat(pDstPicture, &dst_format); + pixel_shift = pDst->drawable.bitsPerPixel >> 4; + + dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation; + dst_pitch = exaGetPixmapPitch(pDst); + colorpitch = dst_pitch >> pixel_shift; + if (RADEONPixmapIsColortiled(pDst)) + colorpitch |= RADEON_COLOR_TILE_ENABLE; + + dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation; + dst_pitch = exaGetPixmapPitch(pDst); + if ((dst_offset & 0x0f) != 0) + RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset)); + if (((dst_pitch >> pixel_shift) & 0x7) != 0) + RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch)); + + if (!FUNC_NAME(R100TextureSetup)(pSrcPicture, pSrc, 0)) + return FALSE; + pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE; + + if (pMask != NULL) { + if (!FUNC_NAME(R100TextureSetup)(pMaskPicture, pMask, 1)) + return FALSE; + pp_cntl |= RADEON_TEX_1_ENABLE; + } else { + is_transform[1] = FALSE; + } + + RADEON_SWITCH_TO_3D(); + + BEGIN_ACCEL(8); + OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl); + OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE); + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset); + OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch); + + /* IN operator: Multiply src by mask components or mask alpha. + * BLEND_CTL_ADD is A * B + C. + * If a picture is a8, we have to explicitly zero its color values. + * If the destination is a8, we have to route the alpha to red, I think. + */ + cblend = RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX | RADEON_COLOR_ARG_C_ZERO; + ablend = RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX | RADEON_ALPHA_ARG_C_ZERO; + + if (pDstPicture->format == PICT_a8) + cblend |= RADEON_COLOR_ARG_A_T0_ALPHA; + else if (pSrcPicture->format == PICT_a8) + cblend |= RADEON_COLOR_ARG_A_ZERO; + else + cblend |= RADEON_COLOR_ARG_A_T0_COLOR; + ablend |= RADEON_ALPHA_ARG_A_T0_ALPHA; + + if (pMask) { + if (pMaskPicture->componentAlpha && + pDstPicture->format != PICT_a8) + cblend |= RADEON_COLOR_ARG_B_T1_COLOR; + else + cblend |= RADEON_COLOR_ARG_B_T1_ALPHA; + ablend |= RADEON_ALPHA_ARG_B_T1_ALPHA; + } else { + cblend |= RADEON_COLOR_ARG_B_ZERO | RADEON_COMP_ARG_B; + ablend |= RADEON_ALPHA_ARG_B_ZERO | RADEON_COMP_ARG_B; + } + + OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0, cblend); + OUT_ACCEL_REG(RADEON_PP_TXABLEND_0, ablend); + OUT_ACCEL_REG(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY | + RADEON_SE_VTX_FMT_ST0 | + RADEON_SE_VTX_FMT_ST1); + /* Op operator. */ + blendcntl = RADEONGetBlendCntl(op, pDstPicture->format); + OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl); + FINISH_ACCEL(); + + return TRUE; +} + +#ifdef ONLY_ONCE + +static Bool R200CheckCompositeTexture(PicturePtr pPict, int unit) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + + if ((w > 0x7ff) || (h > 0x7ff)) + RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); + + for (i = 0; i < sizeof(R200TexFormats) / sizeof(R200TexFormats[0]); i++) + { + if (R200TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(R200TexFormats) / sizeof(R200TexFormats[0])) + RADEON_FALLBACK(("Unsupported picture format 0x%x\n", + (int)pPict->format)); + + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) + RADEON_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h)); + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) + RADEON_FALLBACK(("Unsupported filter 0x%x\n", pPict->filter)); + + return TRUE; +} + +#endif /* ONLY_ONCE */ + +static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix, + int unit) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + CARD32 txfilter, txformat, txoffset, txpitch; + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + ACCEL_PREAMBLE(); + + txpitch = exaGetPixmapPitch(pPix); + txoffset = exaGetPixmapOffset(pPix) + info->fbLocation; + + for (i = 0; i < sizeof(R200TexFormats) / sizeof(R200TexFormats[0]); i++) + { + if (R200TexFormats[i].fmt == pPict->format) + break; + } + txformat = R200TexFormats[i].card_fmt; + if (R200TexFormats[i].byte_swap) + txoffset |= R200_TXO_ENDIAN_BYTE_SWAP; + if (RADEONPixmapIsColortiled(pPix)) + txoffset |= R200_TXO_MACRO_TILE; + + if (pPict->repeat) { + txformat |= RADEONLog2(w) << R200_TXFORMAT_WIDTH_SHIFT; + txformat |= RADEONLog2(h) << R200_TXFORMAT_HEIGHT_SHIFT; + } else + txformat |= R200_TXFORMAT_NON_POWER2; + txformat |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; + + if ((txoffset & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + if ((txpitch & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch)); + + switch (pPict->filter) { + case PictFilterNearest: + txfilter = (R200_MAG_FILTER_NEAREST | + R200_MIN_FILTER_NEAREST); + break; + case PictFilterBilinear: + txfilter = (R200_MAG_FILTER_LINEAR | + R200_MIN_FILTER_LINEAR); + break; + default: + RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter)); + } + + BEGIN_ACCEL(6); + if (unit == 0) { + OUT_ACCEL_REG(R200_PP_TXFILTER_0, txfilter); + OUT_ACCEL_REG(R200_PP_TXFORMAT_0, txformat); + OUT_ACCEL_REG(R200_PP_TXFORMAT_X_0, 0); + OUT_ACCEL_REG(R200_PP_TXSIZE_0, (pPix->drawable.width - 1) | + ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); + OUT_ACCEL_REG(R200_PP_TXPITCH_0, txpitch - 32); + OUT_ACCEL_REG(R200_PP_TXOFFSET_0, txoffset); + } else { + OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter); + OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat); + OUT_ACCEL_REG(R200_PP_TXFORMAT_X_1, 0); + OUT_ACCEL_REG(R200_PP_TXSIZE_1, (pPix->drawable.width - 1) | + ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); + OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch - 32); + OUT_ACCEL_REG(R200_PP_TXOFFSET_1, txoffset); + } + FINISH_ACCEL(); + + if (pPict->transform != 0) { + is_transform[unit] = TRUE; + transform[unit] = pPict->transform; + } else { + is_transform[unit] = FALSE; + } + + return TRUE; +} + +#ifdef ONLY_ONCE +static Bool R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + CARD32 tmp1; + + TRACE; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0])) + RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op)); + if (pMaskPicture != NULL && pMaskPicture->componentAlpha && + RadeonBlendOp[op].src_alpha) + RADEON_FALLBACK(("Component alpha not supported with source " + "alpha blending.\n")); + + if (!R200CheckCompositeTexture(pSrcPicture, 0)) + return FALSE; + if (pMaskPicture != NULL && !R200CheckCompositeTexture(pMaskPicture, 1)) + return FALSE; + + if (!RADEONGetDestFormat(pDstPicture, &tmp1)) + return FALSE; + + return TRUE; +} +#endif /* ONLY_ONCE */ + +static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + RINFO_FROM_SCREEN(pDst->drawable.pScreen); + CARD32 dst_format, dst_offset, dst_pitch; + CARD32 pp_cntl, blendcntl, cblend, ablend, colorpitch; + int pixel_shift; + ACCEL_PREAMBLE(); + + TRACE; + + if (!info->XInited3D) + RADEONInit3DEngine(pScrn); + + RADEONGetDestFormat(pDstPicture, &dst_format); + pixel_shift = pDst->drawable.bitsPerPixel >> 4; + + dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation; + dst_pitch = exaGetPixmapPitch(pDst); + colorpitch = dst_pitch >> pixel_shift; + if (RADEONPixmapIsColortiled(pDst)) + colorpitch |= RADEON_COLOR_TILE_ENABLE; + + if ((dst_offset & 0x0f) != 0) + RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset)); + if (((dst_pitch >> pixel_shift) & 0x7) != 0) + RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch)); + + if (!FUNC_NAME(R200TextureSetup)(pSrcPicture, pSrc, 0)) + return FALSE; + pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE; + + if (pMask != NULL) { + if (!FUNC_NAME(R200TextureSetup)(pMaskPicture, pMask, 1)) + return FALSE; + pp_cntl |= RADEON_TEX_1_ENABLE; + } else { + is_transform[1] = FALSE; + } + + RADEON_SWITCH_TO_3D(); + + BEGIN_ACCEL(11); + + OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl); + OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE); + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset); + + OUT_ACCEL_REG(R200_SE_VTX_FMT_0, R200_VTX_XY); + OUT_ACCEL_REG(R200_SE_VTX_FMT_1, + (2 << R200_VTX_TEX0_COMP_CNT_SHIFT) | + (2 << R200_VTX_TEX1_COMP_CNT_SHIFT)); + + OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch); + + /* IN operator: Multiply src by mask components or mask alpha. + * BLEND_CTL_ADD is A * B + C. + * If a picture is a8, we have to explicitly zero its color values. + * If the destination is a8, we have to route the alpha to red, I think. + */ + cblend = R200_TXC_OP_MADD | R200_TXC_ARG_C_ZERO; + ablend = R200_TXA_OP_MADD | R200_TXA_ARG_C_ZERO; + + if (pDstPicture->format == PICT_a8) + cblend |= R200_TXC_ARG_A_R0_ALPHA; + else if (pSrcPicture->format == PICT_a8) + cblend |= R200_TXC_ARG_A_ZERO; + else + cblend |= R200_TXC_ARG_A_R0_COLOR; + ablend |= R200_TXA_ARG_A_R0_ALPHA; + + if (pMask) { + if (pMaskPicture->componentAlpha && + pDstPicture->format != PICT_a8) + cblend |= R200_TXC_ARG_B_R1_COLOR; + else + cblend |= R200_TXC_ARG_B_R1_ALPHA; + ablend |= R200_TXA_ARG_B_R1_ALPHA; + } else { + cblend |= R200_TXC_ARG_B_ZERO | R200_TXC_COMP_ARG_B; + ablend |= R200_TXA_ARG_B_ZERO | R200_TXA_COMP_ARG_B; + } + + OUT_ACCEL_REG(R200_PP_TXCBLEND_0, cblend); + OUT_ACCEL_REG(R200_PP_TXCBLEND2_0, + R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0); + OUT_ACCEL_REG(R200_PP_TXABLEND_0, ablend); + OUT_ACCEL_REG(R200_PP_TXABLEND2_0, + R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0); + + /* Op operator. */ + blendcntl = RADEONGetBlendCntl(op, pDstPicture->format); + OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl); + FINISH_ACCEL(); + + return TRUE; +} + +#ifdef ACCEL_CP + +#define VTX_DWORD_COUNT 6 + +#define VTX_OUT(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY) \ +do { \ + OUT_RING_F(_dstX); \ + OUT_RING_F(_dstY); \ + OUT_RING_F(_srcX); \ + OUT_RING_F(_srcY); \ + OUT_RING_F(_maskX); \ + OUT_RING_F(_maskY); \ +} while (0) + +#else /* ACCEL_CP */ + +#define VTX_REG_COUNT 6 + +#define VTX_OUT(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY) \ +do { \ + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, _dstX); \ + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, _dstY); \ + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, _srcX); \ + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, _srcY); \ + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, _maskX); \ + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, _maskY); \ +} while (0) + +#endif /* !ACCEL_CP */ + +static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + RINFO_FROM_SCREEN(pDst->drawable.pScreen); + int srcXend, srcYend, maskXend, maskYend; + PictVector v; + ACCEL_PREAMBLE(); + + ENTER_DRAW(0); + + /*ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n", + srcX, srcY, maskX, maskY,dstX, dstY, w, h);*/ + + srcXend = srcX + w; + srcYend = srcY + h; + maskXend = maskX + w; + maskYend = maskY + h; + if (is_transform[0]) { + v.vector[0] = IntToxFixed(srcX); + v.vector[1] = IntToxFixed(srcY); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[0], &v); + srcX = xFixedToInt(v.vector[0]); + srcY = xFixedToInt(v.vector[1]); + v.vector[0] = IntToxFixed(srcXend); + v.vector[1] = IntToxFixed(srcYend); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[0], &v); + srcXend = xFixedToInt(v.vector[0]); + srcYend = xFixedToInt(v.vector[1]); + } + if (is_transform[1]) { + v.vector[0] = IntToxFixed(maskX); + v.vector[1] = IntToxFixed(maskY); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[1], &v); + maskX = xFixedToInt(v.vector[0]); + maskY = xFixedToInt(v.vector[1]); + v.vector[0] = IntToxFixed(maskXend); + v.vector[1] = IntToxFixed(maskYend); + v.vector[2] = xFixed1; + PictureTransformPoint(transform[1], &v); + maskXend = xFixedToInt(v.vector[0]); + maskYend = xFixedToInt(v.vector[1]); + } + +#ifdef ACCEL_CP + if (info->ChipFamily < CHIP_FAMILY_R200) { + BEGIN_RING(4 * VTX_DWORD_COUNT + 3); + OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, + 4 * VTX_DWORD_COUNT + 1)); + OUT_RING(RADEON_CP_VC_FRMT_XY | + RADEON_CP_VC_FRMT_ST0 | + RADEON_CP_VC_FRMT_ST1); + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + RADEON_CP_VC_CNTL_MAOS_ENABLE | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + } else { + BEGIN_RING(4 * VTX_DWORD_COUNT + 2); + OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2, + 4 * VTX_DWORD_COUNT)); + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + } + + VTX_OUT(dstX, dstY, srcX, srcY, maskX, maskY); + VTX_OUT(dstX, dstY + h, srcX, srcYend, maskX, maskYend); + VTX_OUT(dstX + w, dstY + h, srcXend, srcYend, maskXend, maskYend); + VTX_OUT(dstX + w, dstY, srcXend, srcY, maskXend, maskY); + ADVANCE_RING(); +#else /* ACCEL_CP */ + BEGIN_ACCEL(1 + VTX_REG_COUNT * 4); + if (info->ChipFamily < CHIP_FAMILY_R200) { + OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_FAN | + RADEON_VF_PRIM_WALK_DATA | + RADEON_VF_RADEON_MODE | + 4 << RADEON_VF_NUM_VERTICES_SHIFT)); + } else { + OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST | + RADEON_VF_PRIM_WALK_DATA | + 4 << RADEON_VF_NUM_VERTICES_SHIFT)); + } + + VTX_OUT(dstX, dstY, srcX, srcY, maskX, maskY); + VTX_OUT(dstX, dstY + h, srcX, srcYend, maskX, maskYend); + VTX_OUT(dstX + w, dstY + h, srcXend, srcYend, maskXend, maskYend); + VTX_OUT(dstX + w, dstY, srcXend, srcY, maskXend, maskY); + FINISH_ACCEL(); +#endif /* !ACCEL_CP */ + + LEAVE_DRAW(0); +} +#undef VTX_OUT + +#ifdef ONLY_ONCE +static void RadeonDoneComposite(PixmapPtr pDst) +{ + ENTER_DRAW(0); + LEAVE_DRAW(0); +} +#endif /* ONLY_ONCE */ + +#undef ONLY_ONCE diff --git a/src/radeon_mergedfb.c b/src/radeon_mergedfb.c index c04577d..ba0b343 100644 --- a/src/radeon_mergedfb.c +++ b/src/radeon_mergedfb.c @@ -1961,7 +1961,14 @@ RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y) OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK | ((xorigin ? 0 : x1) << 16) | (yorigin ? 0 : y1))); - OUTREG(RADEON_CUR_OFFSET, info->cursor_start + yorigin * stride); +#ifdef USE_EXA + if (info->useEXA) + OUTREG(RADEON_CUR_OFFSET, info->cursorArea->offset + yorigin * stride); +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) + OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + yorigin * stride); +#endif /* USE_XAA */ /* cursor2 */ OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) @@ -1969,9 +1976,14 @@ RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y) OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK | ((xorigin ? 0 : x2) << 16) | (yorigin ? 0 : y2))); - OUTREG(RADEON_CUR2_OFFSET, - info->cursor_start + yorigin * stride); - +#ifdef USE_EXA + if (info->useEXA) + OUTREG(RADEON_CUR2_OFFSET, info->cursorArea->offset + yorigin * stride); +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) + OUTREG(RADEON_CUR2_OFFSET, info->cursor_offset + yorigin * stride); +#endif /* USE_XAA */ } /* radeon Xv helpers */ diff --git a/src/radeon_reg.h b/src/radeon_reg.h index 92418e6..13f5ad0 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -53,6 +53,22 @@ #ifndef _RADEON_REG_H_ #define _RADEON_REG_H_ +#define ATI_DATATYPE_VQ 0 +#define ATI_DATATYPE_CI4 1 +#define ATI_DATATYPE_CI8 2 +#define ATI_DATATYPE_ARGB1555 3 +#define ATI_DATATYPE_RGB565 4 +#define ATI_DATATYPE_RGB888 5 +#define ATI_DATATYPE_ARGB8888 6 +#define ATI_DATATYPE_RGB332 7 +#define ATI_DATATYPE_Y8 8 +#define ATI_DATATYPE_RGB8 9 +#define ATI_DATATYPE_CI16 10 +#define ATI_DATATYPE_VYUY_422 11 +#define ATI_DATATYPE_YVYU_422 12 +#define ATI_DATATYPE_AYUV_444 14 +#define ATI_DATATYPE_ARGB4444 15 + /* Registers for 2D/Video/Overlay */ #define RADEON_ADAPTER_ID 0x0f2c /* PCI */ #define RADEON_AGP_BASE 0x0170 @@ -1226,6 +1242,28 @@ # define RADEON_RB2D_DC_FLUSH_ALL 0xf # define RADEON_RB2D_DC_BUSY (1 << 31) #define RADEON_RB2D_DSTCACHE_MODE 0x3428 + +#define RADEON_RB3D_DSTCACHE_MODE 0x3258 +# define RADEON_RB3D_DC_CACHE_ENABLE (0) +# define RADEON_RB3D_DC_2D_CACHE_DISABLE (1) +# define RADEON_RB3D_DC_3D_CACHE_DISABLE (2) +# define RADEON_RB3D_DC_CACHE_DISABLE (3) +# define RADEON_RB3D_DC_2D_CACHE_LINESIZE_128 (1 << 2) +# define RADEON_RB3D_DC_3D_CACHE_LINESIZE_128 (2 << 2) +# define RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH (1 << 8) +# define RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH (2 << 8) +# define R200_RB3D_DC_2D_CACHE_AUTOFREE (1 << 10) +# define R200_RB3D_DC_3D_CACHE_AUTOFREE (2 << 10) +# define RADEON_RB3D_DC_FORCE_RMW (1 << 16) +# define RADEON_RB3D_DC_DISABLE_RI_FILL (1 << 24) +# define RADEON_RB3D_DC_DISABLE_RI_READ (1 << 25) + +#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325C +# define RADEON_RB3D_DC_FLUSH (3 << 0) +# define RADEON_RB3D_DC_FREE (3 << 2) +# define RADEON_RB3D_DC_FLUSH_ALL 0xf +# define RADEON_RB3D_DC_BUSY (1 << 31) + #define RADEON_REG_BASE 0x0f18 /* PCI */ #define RADEON_REGPROG_INF 0x0f09 /* PCI */ #define RADEON_REVISION_ID 0x0f08 /* PCI */ @@ -2305,6 +2343,11 @@ # define R200_VC_16BIT_SWAP (1 << 0) # define R200_VC_32BIT_SWAP (2 << 0) #define R200_PP_TXFILTER_0 0x2c00 +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFILTER_5 0x2ca0 # define R200_MAG_FILTER_NEAREST (0 << 0) # define R200_MAG_FILTER_LINEAR (1 << 0) # define R200_MAG_FILTER_MASK (1 << 0) @@ -2355,6 +2398,11 @@ # define R200_BORDER_MODE_OGL (0 << 31) # define R200_BORDER_MODE_D3D (1 << 31) #define R200_PP_TXFORMAT_0 0x2c04 +#define R200_PP_TXFORMAT_1 0x2c24 +#define R200_PP_TXFORMAT_2 0x2c44 +#define R200_PP_TXFORMAT_3 0x2c64 +#define R200_PP_TXFORMAT_4 0x2c84 +#define R200_PP_TXFORMAT_5 0x2ca4 # define R200_TXFORMAT_I8 (0 << 0) # define R200_TXFORMAT_AI88 (1 << 0) # define R200_TXFORMAT_RGB332 (2 << 0) @@ -2394,15 +2442,42 @@ # define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) # define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) #define R200_PP_TXFORMAT_X_0 0x2c08 +#define R200_PP_TXFORMAT_X_1 0x2c28 +#define R200_PP_TXFORMAT_X_2 0x2c48 +#define R200_PP_TXFORMAT_X_3 0x2c68 +#define R200_PP_TXFORMAT_X_4 0x2c88 +#define R200_PP_TXFORMAT_X_5 0x2ca8 + #define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */ +#define R200_PP_TXSIZE_1 0x2c2c /* NPOT only */ +#define R200_PP_TXSIZE_2 0x2c4c /* NPOT only */ +#define R200_PP_TXSIZE_3 0x2c6c /* NPOT only */ +#define R200_PP_TXSIZE_4 0x2c8c /* NPOT only */ +#define R200_PP_TXSIZE_5 0x2cac /* NPOT only */ + #define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */ +#define R200_PP_TXPITCH_1 0x2c30 /* NPOT only */ +#define R200_PP_TXPITCH_2 0x2c50 /* NPOT only */ +#define R200_PP_TXPITCH_3 0x2c70 /* NPOT only */ +#define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */ +#define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */ + #define R200_PP_TXOFFSET_0 0x2d00 # define R200_TXO_ENDIAN_NO_SWAP (0 << 0) # define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) # define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) # define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R200_TXO_MACRO_LINEAR (0 << 2) +# define R200_TXO_MACRO_TILE (1 << 2) +# define R200_TXO_MICRO_LINEAR (0 << 3) +# define R200_TXO_MICRO_TILE (1 << 3) # define R200_TXO_OFFSET_MASK 0xffffffe0 # define R200_TXO_OFFSET_SHIFT 5 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_TXOFFSET_5 0x2d78 #define R200_PP_TFACTOR_0 0x2ee0 #define R200_PP_TFACTOR_1 0x2ee4 diff --git a/src/radeon_render.c b/src/radeon_render.c index 32e6a3e..191fb69 100644 --- a/src/radeon_render.c +++ b/src/radeon_render.c @@ -1,7 +1,38 @@ +/* + * Copyright 2004 Eric Anholt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt <anholt@FreeBSD.org> + * Hui Yu <hyu@ati.com> + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif +#ifdef USE_XAA + #include "dixstruct.h" #include "xaa.h" @@ -10,11 +41,6 @@ #ifndef RENDER_GENERIC_HELPER #define RENDER_GENERIC_HELPER -static void RadeonInit3DEngineMMIO(ScrnInfoPtr pScrn); -#ifdef XF86DRI -static void RadeonInit3DEngineCP(ScrnInfoPtr pScrn); -#endif - struct blendinfo { Bool dst_alpha; Bool src_alpha; @@ -228,24 +254,6 @@ ATILog2(int val) return bits - 1; } -static void RadeonInit3DEngine(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR (pScrn); - -#ifdef XF86DRI - if (info->directRenderingEnabled) { - RADEONSAREAPrivPtr pSAREAPriv; - - pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); - RadeonInit3DEngineCP(pScrn); - } else -#endif - RadeonInit3DEngineMMIO(pScrn); - - info->RenderInited3D = TRUE; -} - static void RemoveLinear (FBLinearPtr linear) { @@ -357,61 +365,6 @@ static void RADEONRestoreByteswap(RADEONInfoPtr info) #endif #endif - -static void FUNC_NAME(RadeonInit3DEngine)(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - ACCEL_PREAMBLE(); - - if (info->ChipFamily >= CHIP_FAMILY_R300) { - /* Unimplemented */ - } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280) || - (info->ChipFamily == CHIP_FAMILY_RS300) || - (info->ChipFamily == CHIP_FAMILY_R200)) { - - BEGIN_ACCEL(7); - if (info->ChipFamily == CHIP_FAMILY_RS300) { - OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS); - } else { - OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, 0); - } - OUT_ACCEL_REG(R200_PP_CNTL_X, 0); - OUT_ACCEL_REG(R200_PP_TXMULTI_CTL_0, 0); - OUT_ACCEL_REG(R200_SE_VTX_STATE_CNTL, 0); - OUT_ACCEL_REG(R200_RE_CNTL, 0x0); - /* XXX: correct? Want it to be like RADEON_VTX_ST?_NONPARAMETRIC */ - OUT_ACCEL_REG(R200_SE_VTE_CNTL, R200_VTX_ST_DENORMALIZED); - OUT_ACCEL_REG(R200_SE_VAP_CNTL, R200_VAP_FORCE_W_TO_ONE | - R200_VAP_VF_MAX_VTX_NUM); - FINISH_ACCEL(); - } else { - BEGIN_ACCEL(2); - if ((info->ChipFamily == CHIP_FAMILY_RADEON) || - (info->ChipFamily == CHIP_FAMILY_RV200)) - OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, 0); - else - OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS); - OUT_ACCEL_REG(RADEON_SE_COORD_FMT, - RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | - RADEON_VTX_ST0_NONPARAMETRIC | - RADEON_VTX_ST1_NONPARAMETRIC | - RADEON_TEX1_W_ROUTING_USE_W0); - FINISH_ACCEL(); - } - - BEGIN_ACCEL(3); - OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); - OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, 0x07ff07ff); - OUT_ACCEL_REG(RADEON_SE_CNTL, RADEON_DIFFUSE_SHADE_GOURAUD | - RADEON_BFACE_SOLID | - RADEON_FFACE_SOLID | - RADEON_VTX_PIX_CENTER_OGL | - RADEON_ROUND_MODE_ROUND | - RADEON_ROUND_PREC_4TH_PIX); - FINISH_ACCEL(); -} - static Bool FUNC_NAME(R100SetupTexture)( ScrnInfoPtr pScrn, CARD32 format, @@ -474,9 +427,10 @@ static Bool FUNC_NAME(R100SetupTexture)( while ( height ) { tmp_dst = RADEONHostDataBlit( pScrn, tex_bytepp, width, - dst_pitch, &buf_pitch, - &dst, &height, &hpass ); - RADEONHostDataBlitCopyPass( tmp_dst, src, hpass, buf_pitch, src_pitch ); + dst_pitch, &buf_pitch, + &dst, &height, &hpass); + RADEONHostDataBlitCopyPass( pScrn, tex_bytepp, tmp_dst, src, + hpass, buf_pitch, src_pitch ); src += hpass * src_pitch; } @@ -542,8 +496,8 @@ FUNC_NAME(R100SetupForCPUToScreenAlphaTexture) ( if (blend_cntl == 0) return FALSE; - if (!info->RenderInited3D) - RadeonInit3DEngine(pScrn); + if (!info->XInited3D) + RADEONInit3DEngine(pScrn); if (!FUNC_NAME(R100SetupTexture)(pScrn, maskFormat, alphaPtr, alphaPitch, width, height, flags)) @@ -593,8 +547,8 @@ FUNC_NAME(R100SetupForCPUToScreenTexture) ( if (blend_cntl == 0) return FALSE; - if (!info->RenderInited3D) - RadeonInit3DEngine(pScrn); + if (!info->XInited3D) + RADEONInit3DEngine(pScrn); if (!FUNC_NAME(R100SetupTexture)(pScrn, srcFormat, texPtr, texPitch, width, height, flags)) @@ -805,9 +759,10 @@ static Bool FUNC_NAME(R200SetupTexture)( while ( height ) { tmp_dst = RADEONHostDataBlit( pScrn, tex_bytepp, width, - dst_pitch, &buf_pitch, - &dst, &height, &hpass ); - RADEONHostDataBlitCopyPass( tmp_dst, src, hpass, buf_pitch, src_pitch ); + dst_pitch, &buf_pitch, + &dst, &height, &hpass ); + RADEONHostDataBlitCopyPass( pScrn, tex_bytepp, tmp_dst, src, + hpass, buf_pitch, src_pitch ); src += hpass * src_pitch; } @@ -873,8 +828,8 @@ FUNC_NAME(R200SetupForCPUToScreenAlphaTexture) ( if (blend_cntl == 0) return FALSE; - if (!info->RenderInited3D) - RadeonInit3DEngine(pScrn); + if (!info->XInited3D) + RADEONInit3DEngine(pScrn); if (!FUNC_NAME(R200SetupTexture)(pScrn, maskFormat, alphaPtr, alphaPitch, width, height, flags)) @@ -925,8 +880,8 @@ FUNC_NAME(R200SetupForCPUToScreenTexture) ( if (blend_cntl == 0) return FALSE; - if (!info->RenderInited3D) - RadeonInit3DEngine(pScrn); + if (!info->XInited3D) + RADEONInit3DEngine(pScrn); if (!FUNC_NAME(R200SetupTexture)(pScrn, srcFormat, texPtr, texPitch, width, height, flags)) @@ -1074,4 +1029,4 @@ FUNC_NAME(R200SubsequentCPUToScreenTexture) ( } #undef FUNC_NAME - +#endif /* USE_XAA */ diff --git a/src/radeon_video.c b/src/radeon_video.c index 2c2dffd..6a27616 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -14,6 +14,7 @@ #include "xf86.h" #include "dixstruct.h" #include "xf86PciInfo.h" +#include "xf86fbman.h" #include <X11/extensions/Xv.h> #include "fourcc.h" @@ -24,6 +25,13 @@ #include "msp3430.h" #include "tda9885.h" +#ifdef USE_EXA +/* FIXME : the video code hasn't been ported so this is a hack to make + * it compile at all without too much ifdefing */ +#include "xaa.h" +#include "xf86fbman.h" +#endif + #define OFF_DELAY 250 /* milliseconds */ #define FREE_DELAY 15000 @@ -80,6 +88,7 @@ static int RADEONPutImage(ScrnInfoPtr, short, short, short, short, short, short, Bool, RegionPtr, pointer); static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); +static void RADEONFreeMemory(ScrnInfoPtr pScrn, void *mem_struct); static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now); static int RADEONPutVideo(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y, @@ -114,6 +123,19 @@ static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode; (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) +#ifdef USE_EXA +static void +ATIVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; + + if (pPriv->video_memory == area) + pPriv->video_memory = NULL; +} +#endif /* USE_EXA */ + void RADEONInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1038,7 +1060,8 @@ RADEONResetVideo(ScrnInfoPtr pScrn) /* this function is called from ScreenInit. pScreen is used by XAA internally, but not valid until ScreenInit finishs. */ - if (info->accelOn && pScrn->pScreen) info->accel->Sync(pScrn); + if (info->accelOn && pScrn->pScreen) + RADEON_SYNC(info, pScrn); /* this is done here because each time the server is reset these could change.. Otherwise they remain constant */ @@ -1204,20 +1227,20 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) } else { t->wComp0Connector=RT_COMP1; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %d\n", t->wComp0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %ld\n", t->wComp0Connector); break; case 3: if(a & 0x4){ t->wSVideo0Connector=RT_YCR_COMP4; } else { t->wSVideo0Connector=RT_YCF_COMP4; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %d\n", t->wSVideo0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %ld\n", t->wSVideo0Connector); break; default: break; } } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%d, composite=%d, svideo=%d\n", + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%ld, composite=%ld, svideo=%ld\n", t->wTunerConnector, t->wComp0Connector, t->wSVideo0Connector); } @@ -1226,7 +1249,7 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) if(info->RageTheatreCompositePort>=0)t->wComp0Connector=info->RageTheatreCompositePort; if(info->RageTheatreSVideoPort>=0)t->wSVideo0Connector=info->RageTheatreSVideoPort; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%d, composite=%d, svideo=%d\n", + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%ld, composite=%ld, svideo=%ld\n", t->wTunerConnector, t->wComp0Connector, t->wSVideo0Connector); switch((info->RageTheatreCrystal>=0)?info->RageTheatreCrystal:pll->reference_freq){ @@ -1253,7 +1276,6 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) XF86VideoAdaptorPtr adapt; RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv; - unsigned char *RADEONMMIO = info->MMIO; CARD32 dot_clock; if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) @@ -1531,9 +1553,9 @@ RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) if(pPriv->uda1380 != NULL) xf86_uda1380_mute(pPriv->uda1380, TRUE); if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv); } - if(info->videoLinear) { - xf86FreeOffscreenLinear(info->videoLinear); - info->videoLinear = NULL; + if (pPriv->video_memory != NULL) { + RADEONFreeMemory(pScrn, pPriv->video_memory); + pPriv->video_memory = NULL; } pPriv->videoStatus = 0; } else { @@ -1556,7 +1578,7 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, Bool setAlpha = FALSE; unsigned char *RADEONMMIO = info->MMIO; - info->accel->Sync(pScrn); + RADEON_SYNC(info, pScrn); #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0) #define RTFBrightness(a) (((a)*1.0)/2000.0) @@ -1785,7 +1807,7 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, else if(attribute == xvAdjustment) { pPriv->adjustment=value; - xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %d\n", pPriv->adjustment); + xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %ld\n", pPriv->adjustment); if(pPriv->tda9885!=0){ pPriv->tda9885->top_adjustment=value; RADEON_TDA9885_SetEncoding(pPriv); @@ -1825,7 +1847,7 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn) RADEON_SYNC(info, pScrn); if(attribute == xvAutopaintColorkey) *value = pPriv->autopaint_colorkey; @@ -2008,11 +2030,11 @@ RADEONCopyData( ScrnInfoPtr pScrn, unsigned char *src, unsigned char *dst, - int srcPitch, - int dstPitch, - int h, - int w, - int bpp + unsigned int srcPitch, + unsigned int dstPitch, + unsigned int h, + unsigned int w, + unsigned int bpp ){ RADEONInfoPtr info = RADEONPTR(pScrn); #ifdef XF86DRI @@ -2033,7 +2055,8 @@ RADEONCopyData( while ( buf = RADEONHostDataBlit( pScrn, bpp, w, dstPitch, &bufPitch, &dst, &h, &hpass ) ) { - RADEONHostDataBlitCopyPass( buf, src, hpass, bufPitch, srcPitch ); + RADEONHostDataBlitCopyPass( pScrn, bpp, buf, src, hpass, bufPitch, + srcPitch ); src += hpass * srcPitch; } @@ -2046,24 +2069,25 @@ RADEONCopyData( { #if X_BYTE_ORDER == X_BIG_ENDIAN unsigned char *RADEONMMIO = info->MMIO; - if ( bpp == 2 ) - { - OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl - & ~(RADEON_NONSURF_AP0_SWP_32BPP - | RADEON_NONSURF_AP0_SWP_16BPP)); - } - else /* bpp == 4 */ - { - OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl - | RADEON_NONSURF_AP0_SWP_32BPP) - & ~RADEON_NONSURF_AP0_SWP_16BPP); + unsigned int swapper = info->ModeReg.surface_cntl & + ~(RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP | + RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP); + + switch(bpp) { + case 2: + swapper |= RADEON_NONSURF_AP0_SWP_16BPP + | RADEON_NONSURF_AP1_SWP_16BPP; + break; + case 4: + swapper |= RADEON_NONSURF_AP0_SWP_32BPP + | RADEON_NONSURF_AP1_SWP_32BPP; + break; } + OUTREG(RADEON_SURFACE_CNTL, swapper); #endif + w *= bpp; - w *= 2; - - while (h--) - { + while (h--) { memcpy(dst, src, w); src += srcPitch; dst += dstPitch; @@ -2097,13 +2121,13 @@ RADEONCopyRGB24Data( ScrnInfoPtr pScrn, unsigned char *src, unsigned char *dst, - int srcPitch, - int dstPitch, - int h, - int w + unsigned int srcPitch, + unsigned int dstPitch, + unsigned int h, + unsigned int w ){ CARD32 *dptr; - CARD8 *sptr; + CARD8 *sptr = 0; int i,j; RADEONInfoPtr info = RADEONPTR(pScrn); #ifdef XF86DRI @@ -2113,6 +2137,8 @@ RADEONCopyRGB24Data( CARD32 bufPitch; unsigned int hpass; + /* XXX Fix endian flip on R300 */ + while ( dptr = ( CARD32* )RADEONHostDataBlit( pScrn, 4, w, dstPitch, &bufPitch, &dst, &h, &hpass ) ) @@ -2171,11 +2197,11 @@ RADEONCopyMungedData( unsigned char *src2, unsigned char *src3, unsigned char *dst1, - int srcPitch, - int srcPitch2, - int dstPitch, - int h, - int w + unsigned int srcPitch, + unsigned int srcPitch2, + unsigned int dstPitch, + unsigned int h, + unsigned int w ){ RADEONInfoPtr info = RADEONPTR(pScrn); #ifdef XF86DRI @@ -2186,6 +2212,8 @@ RADEONCopyMungedData( CARD32 y = 0, bufPitch; unsigned int hpass; + /* XXX Fix endian flip on R300 */ + while ( buf = RADEONHostDataBlit( pScrn, 4, w/2, dstPitch, &bufPitch, &dst1, &h, &hpass ) ) { @@ -2249,9 +2277,8 @@ RADEONCopyMungedData( { src2 += srcPitch2; src3 += srcPitch2; - } + } } - #if X_BYTE_ORDER == X_BIG_ENDIAN /* restore byte swapping */ OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); @@ -2259,46 +2286,111 @@ RADEONCopyMungedData( } } - -static FBLinearPtr +/* Allocates memory, either by resizing the allocation pointed to by mem_struct, + * or by freeing mem_struct (if non-NULL) and allocating a new space. The size + * is measured in bytes, and the offset from the beginning of card space is + * returned. + */ +static CARD32 RADEONAllocateMemory( ScrnInfoPtr pScrn, - FBLinearPtr linear, + void **mem_struct, int size ){ - ScreenPtr pScreen; - FBLinearPtr new_linear; + ScreenPtr pScreen; + RADEONInfoPtr info = RADEONPTR(pScrn); + int offset = 0; - if(linear) { - if(linear->size >= size) - return linear; + pScreen = screenInfo.screens[pScrn->scrnIndex]; +#ifdef USE_EXA + if (info->useEXA) { + ExaOffscreenArea *area = *mem_struct; - if(xf86ResizeOffscreenLinear(linear, size)) - return linear; + if (area != NULL) { + if (area->size >= size) + return area->offset; - xf86FreeOffscreenLinear(linear); - } + exaOffscreenFree(pScrn->pScreen, area); + } - pScreen = screenInfo.screens[pScrn->scrnIndex]; + area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, ATIVideoSave, + NULL); + *mem_struct = area; + if (area == NULL) + return 0; + offset = area->offset; + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + FBLinearPtr linear = *mem_struct; + int cpp = info->CurrentLayout.bitsPerPixel / 8; + + /* XAA allocates in units of pixels at the screen bpp, so adjust size + * appropriately. + */ + size = (size + cpp - 1) / cpp; + + if (linear) { + if(linear->size >= size) + return linear->offset * cpp; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear->offset * cpp; + + xf86FreeOffscreenLinear(linear); + } - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, NULL, NULL); + *mem_struct = linear; - if(!new_linear) { - int max_size; + if (!linear) { + int max_size; - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, - PRIORITY_EXTREME); + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, + PRIORITY_EXTREME); - if(max_size < size) - return NULL; + if(max_size < size) + return 0; - xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, - NULL, NULL, NULL); - } + xf86PurgeUnlockedOffscreenAreas(pScreen); + linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + *mem_struct = linear; + if (!linear) + return 0; + } + offset = linear->offset * cpp; + } +#endif /* USE_XAA */ - return new_linear; + return offset; +} + +static void +RADEONFreeMemory( + ScrnInfoPtr pScrn, + void *mem_struct +){ + RADEONInfoPtr info = RADEONPTR(pScrn); + +#ifdef USE_EXA + if (info->useEXA) { + ExaOffscreenArea *area = mem_struct; + + if (area != NULL) + exaOffscreenFree(pScrn->pScreen, area); + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + FBLinearPtr linear = mem_struct; + + if (linear != NULL) + xf86FreeOffscreenLinear(linear); + } +#endif /* USE_XAA */ } static void @@ -2478,7 +2570,7 @@ RADEONDisplayVideo( RADEONWaitForFifo(pScrn, 2); OUTREG(RADEON_OV0_REG_LOAD_CNTL, 1); - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn) RADEON_SYNC(info, pScrn); while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & (1 << 3))); dsr=(double)(1<<0xC)/h_inc; @@ -2686,27 +2778,22 @@ RADEONPutImage( case FOURCC_RGB24: dstPitch=(width*4+0x0f)&(~0x0f); srcPitch=width*3; - new_size=(dstPitch*height+bpp-1)/bpp; break; case FOURCC_RGBA32: dstPitch=(width*4+0x0f)&(~0x0f); srcPitch=width*4; - new_size=(dstPitch*height+bpp-1)/bpp; break; case FOURCC_RGBT16: dstPitch=(width*2+0x0f)&(~0x0f); srcPitch=(width*2+3)&(~0x03); - new_size=(dstPitch*height+bpp-1)/bpp; break; case FOURCC_RGB16: dstPitch=(width*2+0x0f)&(~0x0f); srcPitch=(width*2+3)&(~0x03); - new_size=(dstPitch*height+bpp-1)/bpp; break; case FOURCC_YV12: case FOURCC_I420: dstPitch = ((width << 1) + 63) & ~63; - new_size = ((dstPitch * height) + bpp - 1) / bpp; srcPitch = (width + 3) & ~3; s2offset = srcPitch * height; srcPitch2 = ((width >> 1) + 3) & ~3; @@ -2716,16 +2803,16 @@ RADEONPutImage( case FOURCC_YUY2: default: dstPitch = ((width << 1) + 63) & ~63; - new_size = ((dstPitch * height) + bpp - 1) / bpp; srcPitch = (width << 1); break; } - if(!(info->videoLinear = RADEONAllocateMemory(pScrn, info->videoLinear, - pPriv->doubleBuffer ? (new_size << 1) : new_size))) - { - return BadAlloc; - } + new_size = dstPitch * height; + pPriv->video_offset = RADEONAllocateMemory(pScrn, &pPriv->video_memory, + (pPriv->doubleBuffer ? + (new_size * 2) : new_size)); + if (pPriv->video_offset == 0) + return BadAlloc; pPriv->currentBuffer ^= 1; @@ -2734,9 +2821,10 @@ RADEONPutImage( left = (xa >> 16) & ~1; npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; - offset = (info->videoLinear->offset * bpp) + (top * dstPitch); + offset = (pPriv->video_offset) + (top * dstPitch); + if(pPriv->doubleBuffer) - offset += pPriv->currentBuffer * new_size * bpp; + offset += pPriv->currentBuffer * new_size; dst_start = info->FB + offset; @@ -2861,9 +2949,9 @@ RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now) } } else { /* FREE_TIMER */ if(pPriv->freeTime < now) { - if(info->videoLinear) { - xf86FreeOffscreenLinear(info->videoLinear); - info->videoLinear = NULL; + if (pPriv->video_memory != NULL) { + RADEONFreeMemory(pScrn, pPriv->video_memory); + pPriv->video_memory = NULL; } pPriv->videoStatus = 0; info->VideoTimerCallback = NULL; @@ -2875,7 +2963,7 @@ RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now) /****************** Offscreen stuff ***************/ typedef struct { - FBLinearPtr linear; + void *surface_memory; Bool isOn; } OffscreenPrivRec, * OffscreenPrivPtr; @@ -2887,46 +2975,46 @@ RADEONAllocateSurface( unsigned short h, XF86SurfacePtr surface ){ - FBLinearPtr linear; - int pitch, size, bpp; + int offset, pitch, size; OffscreenPrivPtr pPriv; + void *surface_memory = NULL; if((w > 1024) || (h > 1024)) return BadAlloc; w = (w + 1) & ~1; pitch = ((w << 1) + 15) & ~15; - bpp = pScrn->bitsPerPixel >> 3; - size = ((pitch * h) + bpp - 1) / bpp; + size = pitch * h; - if(!(linear = RADEONAllocateMemory(pScrn, NULL, size))) + offset = RADEONAllocateMemory(pScrn, &surface_memory, size); + if (offset == 0) return BadAlloc; surface->width = w; surface->height = h; if(!(surface->pitches = xalloc(sizeof(int)))) { - xf86FreeOffscreenLinear(linear); + RADEONFreeMemory(pScrn, surface_memory); return BadAlloc; } if(!(surface->offsets = xalloc(sizeof(int)))) { xfree(surface->pitches); - xf86FreeOffscreenLinear(linear); + RADEONFreeMemory(pScrn, surface_memory); return BadAlloc; } if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { xfree(surface->pitches); xfree(surface->offsets); - xf86FreeOffscreenLinear(linear); + RADEONFreeMemory(pScrn, surface_memory); return BadAlloc; } - pPriv->linear = linear; + pPriv->surface_memory = surface_memory; pPriv->isOn = FALSE; surface->pScrn = pScrn; surface->id = id; surface->pitches[0] = pitch; - surface->offsets[0] = linear->offset * bpp; + surface->offsets[0] = offset; surface->devPrivate.ptr = (pointer)pPriv; return Success; @@ -2952,11 +3040,12 @@ static int RADEONFreeSurface( XF86SurfacePtr surface ){ + ScrnInfoPtr pScrn = surface->pScrn; OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; if(pPriv->isOn) RADEONStopSurface(surface); - xf86FreeOffscreenLinear(pPriv->linear); + RADEONFreeMemory(pScrn, pPriv->surface_memory); xfree(surface->pitches); xfree(surface->offsets); xfree(surface->devPrivate.ptr); @@ -3107,7 +3196,9 @@ RADEONPutVideo( RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; unsigned char *RADEONMMIO = info->MMIO; INT32 xa, xb, ya, yb, top; - unsigned int pitch, new_size, offset1, offset2, offset3, offset4, s2offset, s3offset, vbi_offset0, vbi_offset1; + unsigned int pitch, new_size, alloc_size; + unsigned int offset1, offset2, offset3, offset4, s2offset, s3offset; + unsigned int vbi_offset0, vbi_offset1; int srcPitch, srcPitch2, dstPitch; int bpp; BoxRec dstBox; @@ -3116,7 +3207,7 @@ RADEONPutVideo( int mult; int vbi_line_width, vbi_start, vbi_end; - info->accel->Sync(pScrn); + RADEON_SYNC(info, pScrn); /* * s2offset, s3offset - byte offsets into U and V plane of the * source where copying starts. Y plane is @@ -3200,7 +3291,6 @@ RADEONPutVideo( case FOURCC_I420: top &= ~1; dstPitch = ((width << 1) + 15) & ~15; - new_size = ((dstPitch * height) + bpp - 1) / bpp; srcPitch = (width + 3) & ~3; s2offset = srcPitch * height; srcPitch2 = ((width >> 1) + 3) & ~3; @@ -3210,16 +3300,21 @@ RADEONPutVideo( case FOURCC_YUY2: default: dstPitch = ((width<<1) + 15) & ~15; - new_size = ((dstPitch * height) + bpp - 1) / bpp; srcPitch = (width<<1); break; } + new_size = dstPitch * height; new_size = new_size + 0x1f; /* for aligning */ - if(!(info->videoLinear = RADEONAllocateMemory(pScrn, info->videoLinear, new_size*mult+(pPriv->capture_vbi_data?2*2*vbi_line_width*21:0)))) - { - return BadAlloc; - } + alloc_size = new_size * mult; + if (pPriv->capture_vbi_data) + alloc_size += 2 * 2 * vbi_line_width * 21; + + pPriv->video_offset = RADEONAllocateMemory(pScrn, &pPriv->video_memory, + (pPriv->doubleBuffer ? + (new_size * 2) : new_size)); + if (pPriv->video_offset == 0) + return BadAlloc; /* I have suspicion that capture engine must be active _before_ Rage Theatre is being manipulated with.. */ @@ -3232,20 +3327,20 @@ RADEONPutVideo( switch(pPriv->overlay_deinterlacing_method){ case METHOD_BOB: case METHOD_SINGLE: - offset1 = (info->videoLinear->offset*bpp+0xf) & (~0xf); - offset2 = ((info->videoLinear->offset+new_size)*bpp + 0xf) & (~0xf); + offset1 = (pPriv->video_offset + 0xf) & (~0xf); + offset2 = (pPriv->video_offset + new_size + 0xf) & (~0xf); offset3 = offset1; offset4 = offset2; break; case METHOD_WEAVE: - offset1 = (info->videoLinear->offset*bpp+0xf) & (~0xf); + offset1 = (pPriv->video_offset + 0xf) & (~0xf); offset2 = offset1+dstPitch; - offset3 = ((info->videoLinear->offset+2*new_size)*bpp + 0xf) & (~0xf); + offset3 = (pPriv->video_offset + 2 * new_size + 0xf) & (~0xf); offset4 = offset3+dstPitch; break; default: - offset1 = (info->videoLinear->offset*bpp+0xf) & (~0xf); - offset2 = ((info->videoLinear->offset+new_size)*bpp + 0xf) & (~0xf); + offset1 = (pPriv->video_offset + 0xf) & (~0xf); + offset2 = (pPriv->video_offset + new_size + 0xf) & (~0xf); offset3 = offset1; offset4 = offset2; } @@ -3268,8 +3363,7 @@ RADEONPutVideo( vbi_end = 20; } - - vbi_offset0 = ((info->videoLinear->offset+mult*new_size)*bpp+0xf) & (~0xf); + vbi_offset0 = (pPriv->video_offset + mult * new_size * bpp + 0xf) & (~0xf); vbi_offset1 = vbi_offset0 + dstPitch*20; OUTREG(RADEON_CAP0_VBI0_OFFSET, vbi_offset0+display_base); OUTREG(RADEON_CAP0_VBI1_OFFSET, vbi_offset1+display_base); diff --git a/src/radeon_video.h b/src/radeon_video.h index 5894c8d..33e78df 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -81,6 +81,14 @@ typedef struct { Bool autopaint_colorkey; Bool crt2; /* 0=CRT1, 1=CRT2 */ +#ifdef USE_EXA + int size; + ExaOffscreenArea *off_screen; +#endif + + void *video_memory; + int video_offset; + Atom device_id, location_id, instance_id; } RADEONPortPrivRec, *RADEONPortPrivPtr; |