diff options
-rw-r--r-- | man/radeon.man | 14 | ||||
-rw-r--r-- | src/radeon.h | 6 | ||||
-rw-r--r-- | src/radeon_accel.c | 9 | ||||
-rw-r--r-- | src/radeon_accelfuncs.c | 99 | ||||
-rw-r--r-- | src/radeon_common.h | 17 | ||||
-rw-r--r-- | src/radeon_dri.c | 123 | ||||
-rw-r--r-- | src/radeon_driver.c | 454 | ||||
-rw-r--r-- | src/radeon_reg.h | 18 | ||||
-rw-r--r-- | src/radeon_render.c | 73 | ||||
-rw-r--r-- | src/radeon_sarea.h | 3 | ||||
-rw-r--r-- | src/radeon_version.h | 1 |
11 files changed, 613 insertions, 204 deletions
diff --git a/man/radeon.man b/man/radeon.man index 82fb1ce..e7c34ff 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -407,6 +407,20 @@ For example, Option "MergedDPI" "100 100" .br The default value is .B undefined. +.TP +.BI "Option \*qEnableColorTiling\*q \*q" "boolean" \*q +Frame buffer can be addressed either in linear or tiled mode. Tiled mode can provide +significant performance benefits with 3D applications, for 2D it shouldn't matter +much. Tiling will be disabled if the virtual x resolution exceeds 2048, if option +.B UseFBDev +is used, or (if DRI is enabled) the drm module is too old. +.br +If this option is enabled, a new dri driver is required for direct rendering too. +.br +Color tiling will be automatically disabled in interlaced or doublescan screen modes. +.br +The default value is +.B on. .TP .BI "Option \*qIgnoreEDID\*q \*q" boolean \*q Do not use EDID data for mode validation, but DDC is still used diff --git a/src/radeon.h b/src/radeon.h index 48be212..20fad25 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -142,6 +142,8 @@ typedef struct { CARD32 clock_cntl_index; CARD32 amcgpio_en_reg; CARD32 amcgpio_mask; + + CARD32 surfaces[8][3]; /* CRTC registers */ CARD32 crtc_gen_cntl; @@ -367,6 +369,8 @@ typedef struct { xf86CursorInfoPtr cursor; unsigned long cursor_start; unsigned long cursor_end; + Bool allowColorTiling; + Bool tilingEnabled; /* mirror of sarea->tiling_enabled */ #ifdef ARGB_CURSOR Bool cursor_argb; #endif @@ -654,7 +658,7 @@ extern unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr); extern void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn); extern void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn); -extern void RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer); +extern void RADEONChangeSurfaces(ScrnInfoPtr pScrn); extern Bool RADEONAccelInit(ScreenPtr pScreen); extern void RADEONAccelInitMMIO(ScreenPtr pScreen, XAAInfoRecPtr a); diff --git a/src/radeon_accel.c b/src/radeon_accel.c index d11c7c8..e2f479d 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -303,9 +303,9 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; - RADEONWaitForFifo(pScrn, 1); - OUTREG(RADEON_DEFAULT_OFFSET, ((info->fbLocation >> 10) - | (pitch64 << 22))); +/* RADEONWaitForFifo(pScrn, 2); + OUTREG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset); + OUTREG(RADEON_SRC_PITCH_OFFSET, info->dst_pitch_offset);*/ RADEONWaitForFifo(pScrn, 1); #if X_BYTE_ORDER == X_BIG_ENDIAN @@ -376,7 +376,8 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) info->dp_gui_master_cntl = ((info->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) - | RADEON_GMC_CLR_CMP_CNTL_DIS); + | RADEON_GMC_CLR_CMP_CNTL_DIS + | RADEON_GMC_DST_PITCH_OFFSET_CNTL); #ifdef XF86DRI info->sc_left = 0x00000000; diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c index 417b0ec..872a717 100644 --- a/src/radeon_accelfuncs.c +++ b/src/radeon_accelfuncs.c @@ -177,21 +177,15 @@ FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn) #ifdef ACCEL_MMIO - CARD32 pitch64; - - pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; - - OUTREG(RADEON_DEFAULT_OFFSET, ((info->fbLocation + pScrn->fbOffset) >> 10) - | (pitch64 << 22)); - +/* OUTREG(RADEON_DEFAULT_OFFSET, info->dst_pitch_offset);*/ /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */ RADEONWaitForIdleMMIO(pScrn); #else /* ACCEL_CP */ - RADEONWaitForFifo(pScrn, 1); - OUTREG(RADEON_DEFAULT_OFFSET, info->frontPitchOffset); +/* RADEONWaitForFifo(pScrn, 1); + OUTREG(RADEON_DEFAULT_OFFSET, info->frontPitchOffset);*/ RADEONWaitForIdleMMIO(pScrn); @@ -243,8 +237,10 @@ FUNC_NAME(RADEONSubsequentSolidFillRect)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); - BEGIN_ACCEL(2); + BEGIN_ACCEL(3); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h); @@ -298,10 +294,12 @@ FUNC_NAME(RADEONSubsequentSolidHorVertLine)(ScrnInfoPtr pScrn, if (dir == DEGREES_0) w = len; else h = len; - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); 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, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h); @@ -331,8 +329,10 @@ FUNC_NAME(RADEONSubsequentSolidTwoPointLine)(ScrnInfoPtr pScrn, xb, yb, 1, DEGREES_0); - BEGIN_ACCEL(2); + BEGIN_ACCEL(3); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa); OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb); @@ -414,12 +414,14 @@ FUNC_NAME(RADEONDashedLastPel)(ScrnInfoPtr pScrn, dp_gui_master_cntl &= ~RADEON_GMC_SRC_DATATYPE_MASK; dp_gui_master_cntl |= RADEON_GMC_SRC_DATATYPE_COLOR; - BEGIN_ACCEL(7); + BEGIN_ACCEL(8); OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, dp_gui_master_cntl); - OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); 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, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); + OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (1 << 16) | 1); @@ -460,8 +462,10 @@ FUNC_NAME(RADEONSubsequentDashedTwoPointLine)(ScrnInfoPtr pScrn, FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->dash_bg); } - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa); OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT, phase); OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb); @@ -517,7 +521,8 @@ FUNC_NAME(RADEONSetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, | RADEON_GMC_BRUSH_NONE | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP[rop].rop - | RADEON_DP_SRC_SOURCE_MEMORY); + | RADEON_DP_SRC_SOURCE_MEMORY + | RADEON_GMC_SRC_PITCH_OFFSET_CNTL); BEGIN_ACCEL(3); @@ -546,8 +551,12 @@ FUNC_NAME(RADEONSubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, if (info->xdir < 0) xa += w - 1, xb += w - 1; if (info->ydir < 0) ya += h - 1, yb += h - 1; - BEGIN_ACCEL(3); + BEGIN_ACCEL(5); + OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (yb <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_SRC_Y_X, (ya << 16) | xa); OUT_ACCEL_REG(RADEON_DST_Y_X, (yb << 16) | xb); OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); @@ -631,8 +640,10 @@ FUNC_NAME(RADEONSubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (patterny << 8) | patternx); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); @@ -684,8 +695,10 @@ FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (paty << 16) | patx); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); @@ -695,7 +708,7 @@ FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, #endif #ifdef ACCEL_CP -#define CP_BUFSIZE (info->indirectBuffer->total/4-9) +#define CP_BUFSIZE (info->indirectBuffer->total/4-10) /* Helper function to write out a HOSTDATA_BLT packet into the indirect * buffer and set the XAA scratch buffer address appropriately. @@ -712,10 +725,12 @@ RADEONCPScanlinePacket(ScrnInfoPtr pScrn, int bufno) "CPScanline Packet h=%d hpass=%d chunkwords=%d\n", info->scanline_h, info->scanline_hpass, chunk_words); } - BEGIN_RING(chunk_words+9); + BEGIN_RING(chunk_words+10); - OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT,chunk_words+9-2)); + OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT,chunk_words+10-2)); OUT_RING(info->dp_gui_master_cntl_clip); + OUT_RING(info->dst_pitch_offset | + ((info->tilingEnabled && (info->scanline_y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_RING((info->scanline_y << 16) | (info->scanline_x1clip & 0xffff)); OUT_RING(((info->scanline_y+info->scanline_hpass) << 16) | @@ -839,9 +854,11 @@ FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr info->scanline_direct = 0; } - BEGIN_ACCEL(4 + (info->scanline_direct ? + BEGIN_ACCEL(5 + (info->scanline_direct ? (info->scanline_words * h) : 0)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft) & 0xffff)); OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff)); @@ -1029,9 +1046,11 @@ FUNC_NAME(RADEONSubsequentScanlineImageWriteRect)(ScrnInfoPtr pScrn, info->scanline_direct = 0; } - BEGIN_ACCEL(4 + (info->scanline_direct ? + BEGIN_ACCEL(5 + (info->scanline_direct ? (info->scanline_words * h) : 0)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft) & 0xffff)); OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff)); @@ -1138,38 +1157,6 @@ FUNC_NAME(RADEONDisableClipping)(ScrnInfoPtr pScrn) FUNC_NAME(RADEONSetTransparency)(pScrn, info->trans_color); } -#ifdef ACCEL_CP -/* Point the DST_PITCH_OFFSET register at the current buffer. This - * allows us to interact with the back and depth buffers. All CP 2D - * acceleration commands use the DST_PITCH_OFFSET register. - */ -void -RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - ACCEL_PREAMBLE(); - - switch (buffer) { - case RADEON_BACK: - info->dst_pitch_offset = info->backPitchOffset; - break; - case RADEON_DEPTH: - info->dst_pitch_offset = info->depthPitchOffset; - break; - default: - case RADEON_FRONT: - info->dst_pitch_offset = info->frontPitchOffset; - break; - } - - BEGIN_ACCEL(1); - - OUT_ACCEL_REG(RADEON_DEFAULT_OFFSET, info->dst_pitch_offset); - - FINISH_ACCEL(); -} -#endif - void FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) { diff --git a/src/radeon_common.h b/src/radeon_common.h index 3fabc1e..314ce9d 100644 --- a/src/radeon_common.h +++ b/src/radeon_common.h @@ -31,7 +31,7 @@ * Converted to common header format: * Jens Owen <jens@tungstengraphics.com> * - * $XdotOrg: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.3 2004/06/16 09:43:58 anholt Exp $ + * $XdotOrg: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.4 2004/12/12 16:05:35 volodya Exp $ * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.8tsi Exp $ * */ @@ -74,6 +74,8 @@ #define DRM_RADEON_IRQ_WAIT 0x17 #define DRM_RADEON_CP_RESUME 0x18 #define DRM_RADEON_SETPARAM 0x19 +#define DRM_RADEON_SURF_ALLOC 0x1a +#define DRM_RADEON_SURF_FREE 0x1b #define DRM_RADEON_MAX_DRM_COMMAND_INDEX 0x39 @@ -470,6 +472,19 @@ typedef struct drm_radeon_set_param { } drmRadeonSetParam; #define RADEON_SETPARAM_FB_LOCATION 1 +#define RADEON_SETPARAM_SWITCH_TILING 2 + +/* 1.14: Clients can allocate/free a surface + */ +typedef struct drm_radeon_surface_alloc { + unsigned int address; + unsigned int size; + unsigned int flags; +} drmRadeonSurfaceAlloc; + +typedef struct drm_radeon_surface_free { + unsigned int address; +} drmRadeonSurfaceFree; #endif diff --git a/src/radeon_dri.c b/src/radeon_dri.c index 450895b..7213223 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -446,73 +446,23 @@ static void RADEONDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, } } -/* The Radeon has depth tiling on all the time, so we have to convert - * the x,y coordinates into the memory bus address (mba) in the same - * manner as the engine. In each case, the linear block address (ba) - * is calculated, and then wired with x and y to produce the final - * memory address. +/* The Radeon has depth tiling on all the time. Rely on surface regs to + * translate the addresses (only works if allowColorTiling is true). */ -static CARD32 radeon_mba_z16(RADEONInfoPtr info, int x, int y) -{ - CARD32 pitch = info->frontPitch; - CARD32 address = 0; /* a[0] = 0 */ - CARD32 ba; - - ba = (y / 16) * (pitch / 32) + (x / 32); - - address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */ - address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */ - address |= (x & 0x8) << 4; /* a[7] = x[3] */ - address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ - address |= (y & 0x8) << 7; /* a[10] = y[3] */ - address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */ - address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */ - - return address; -} - -static CARD32 radeon_mba_z32(RADEONInfoPtr info, int x, int y) -{ - CARD32 pitch = info->frontPitch; - CARD32 address = 0; /* a[0..1] = 0 */ - CARD32 ba; - - ba = (y / 16) * (pitch / 16) + (x / 16); - - address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */ - address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */ - address |= - (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */ - address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ - - address |= (y & 0x8) << 7; /* a[10] = y[3] */ - address |= - (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */ - address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */ - - return address; -} /* 16-bit depth buffer functions */ #define WRITE_DEPTH16(_x, _y, d) \ - *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y))) = (d) + *(CARD16 *)(pointer)(buf + 2*(_x + _y*info->frontPitch)) = (d) #define READ_DEPTH16(d, _x, _y) \ - (d) = *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y))) - -/* 24 bit depth, 8 bit stencil depthbuffer functions */ -#define WRITE_DEPTH32(_x, _y, d) \ -do { \ - CARD32 tmp = \ - *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))); \ - tmp &= 0xff000000; \ - tmp |= ((d) & 0x00ffffff); \ - *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) = tmp; \ -} while (0) - -#define READ_DEPTH32(d, _x, _y) \ - d = (*(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) \ - & 0x00ffffff) + (d) = *(CARD16 *)(pointer)(buf + 2*(_x + _y*info->frontPitch)) + +/* 32-bit depth buffer (stencil and depth simultaneously) functions */ +#define WRITE_DEPTHSTENCIL32(_x, _y, d) \ + *(CARD32 *)(pointer)(buf + 4*(_x + _y*info->frontPitch)) = (d) + +#define READ_DEPTHSTENCIL32(d, _x, _y) \ + (d) = *(CARD32 *)(pointer)(buf + 4*(_x + _y*info->frontPitch)) /* Screen to screen copy of data in the depth buffer */ static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn, @@ -545,8 +495,8 @@ static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn, case 32: for (x = xstart; x != xend; x += xdir) { for (y = ystart; y != yend; y += ydir) { - READ_DEPTH32(d, xa+x, ya+y); - WRITE_DEPTH32(xb+x, yb+y, d); + READ_DEPTHSTENCIL32(d, xa+x, ya+y); + WRITE_DEPTHSTENCIL32(xb+x, yb+y, d); } } break; @@ -684,6 +634,11 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, xdir = 1; } + /* pretty much a hack. */ + info->dst_pitch_offset = info->backPitchOffset; + if (info->tilingEnabled) + info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; + (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, (CARD32)(-1), -1); @@ -703,14 +658,12 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, if (w <= 0) continue; if (h <= 0) continue; - RADEONSelectBuffer(pScrn, RADEON_BACK); (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, destx, desty, w, h); if (info->depthMoves) { - RADEONSelectBuffer(pScrn, RADEON_DEPTH); RADEONScreenToScreenCopyDepth(pScrn, xa, ya, destx, desty, @@ -718,7 +671,7 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, } } - RADEONSelectBuffer(pScrn, RADEON_FRONT); + info->dst_pitch_offset = info->frontPitchOffset;; DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); @@ -1228,7 +1181,7 @@ static void RADEONDRICPInit(ScrnInfoPtr pScrn) /* Make sure the CP is on for the X server */ RADEONCP_START(pScrn, info); - RADEONSelectBuffer(pScrn, RADEON_FRONT); + info->dst_pitch_offset = info->frontPitchOffset; } @@ -1316,7 +1269,8 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) info->PciInfo->device, info->PciInfo->func); } - pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR; + pDRIInfo->ddxDriverMajorVersion = info->allowColorTiling ? + RADEON_VERSION_MAJOR_TILED : RADEON_VERSION_MAJOR; pDRIInfo->ddxDriverMinorVersion = RADEON_VERSION_MINOR; pDRIInfo->ddxDriverPatchVersion = RADEON_VERSION_PATCH; pDRIInfo->frameBufferPhysicalAddress = info->LinearAddr; @@ -1484,6 +1438,24 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) version->version_patchlevel); } info->drmMinor = version->version_minor; + + if (info->allowColorTiling && version->version_minor < 14) { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[dri] color tiling disabled because of version " + "mismatch.\n" + "[dri] radeon.o kernel module version is %d.%d.%d but " + "1.14.0 or later is required for color tiling.\n", + version->version_major, + version->version_minor, + version->version_patchlevel); + info->allowColorTiling = FALSE; + info->tilingEnabled = FALSE; + /* try to fix up already set mode, crt pitch, ddx major (hope that's ok to do here) */ + /* is this correct scrnIndex? flags? */ + RADEONSwitchMode(pScrn->scrnIndex, pScrn->currentMode, 0); + pScrn->AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR; + } drmFreeVersion(version); } @@ -1820,6 +1792,9 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) return; + /* pretty much a hack. */ + if (info->tilingEnabled) + info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, (CARD32)(-1), -1); @@ -1836,6 +1811,7 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) yb - ya + 1); } } + info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; } static void RADEONEnablePageFlip(ScreenPtr pScreen) @@ -1845,6 +1821,9 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); if (info->allowPageFlip) { + /* pretty much a hack. */ + if (info->tilingEnabled) + info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; /* Duplicate the frontbuffer to the backbuffer */ (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, @@ -1858,6 +1837,7 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) pScrn->virtualX, pScrn->virtualY); + info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; pSAREAPriv->pfAllowPageFlip = 1; } } @@ -1947,10 +1927,11 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) xf86FreeOffscreenArea(fbarea); - RADEONEnablePageFlip(pScreen); - info->have3DWindows = 1; + RADEONChangeSurfaces(pScrn); + RADEONEnablePageFlip(pScreen); + if (info->cursor_start) xf86ForceHWCursor (pScreen, TRUE); } @@ -1980,6 +1961,8 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) info->have3DWindows = 0; + RADEONChangeSurfaces(pScrn); + if (info->cursor_start) xf86ForceHWCursor (pScreen, FALSE); } diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 340ba3b..9cbbdb2 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -161,6 +161,7 @@ typedef enum { OPTION_DISP_PRIORITY, OPTION_PANEL_SIZE, OPTION_MIN_DOTCLOCK, + OPTION_COLOR_TILING, #ifdef XvExtension OPTION_VIDEO_KEY, OPTION_RAGE_THEATRE_CRYSTAL, @@ -217,6 +218,7 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_DISP_PRIORITY, "DisplayPriority", OPTV_ANYSTR, {0}, FALSE }, { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, { OPTION_MIN_DOTCLOCK, "ForceMinDotClock", OPTV_FREQ, {0}, FALSE }, + { OPTION_COLOR_TILING, "EnableColorTiling",OPTV_BOOLEAN, {0}, FALSE }, #ifdef XvExtension { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, { OPTION_RAGE_THEATRE_CRYSTAL, "RageTheatreCrystal", OPTV_INTEGER, {0}, FALSE }, @@ -1223,7 +1225,7 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) long start_secs, start_usecs, stop_secs, stop_usecs, total_usecs; long to1_secs, to1_usecs, to2_secs, to2_usecs; unsigned int f1, f2, f3; - int i, tries = 0; + int tries = 0; prev_xtal = 0; again: @@ -2895,13 +2897,20 @@ static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first, static void RADEONSetPitch (ScrnInfoPtr pScrn) { int dummy = pScrn->virtualX; + RADEONInfoPtr info = RADEONPTR(pScrn); /* FIXME: May need to validate line pitch here */ switch (pScrn->depth / 8) { - case 1: dummy = (pScrn->virtualX + 127) & ~127; break; - case 2: dummy = (pScrn->virtualX + 31) & ~31; break; + case 1: if (info->allowColorTiling) dummy = (pScrn->virtualX + 255) & ~255; + else dummy = (pScrn->virtualX + 127) & ~127; + break; + case 2: if (info->allowColorTiling) dummy = (pScrn->virtualX + 127) & ~127; + else dummy = (pScrn->virtualX + 31) & ~31; + break; case 3: - case 4: dummy = (pScrn->virtualX + 15) & ~15; break; + case 4: if (info->allowColorTiling) dummy = (pScrn->virtualX + 63) & ~63; + else dummy = (pScrn->virtualX + 15) & ~15; + break; } pScrn->displayWidth = dummy; } @@ -3538,7 +3547,8 @@ static int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 64 * pScrn1->bitsPerPixel, /* pitchInc */ + info->allowColorTiling ? 2048 : + 64 * pScrn1->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ 8 * 1024, /*2048,*/ /* maxHeight */ pScrn1->display->virtualX ? pScrn1->virtualX : 0, @@ -3600,7 +3610,8 @@ static int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 64 * pScrn1->bitsPerPixel, /* pitchInc */ + info->allowColorTiling ? 2048 : + 64 * pScrn1->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ 8 * 1024, /*2048,*/ /* maxHeight */ pScrn1->display->virtualX, @@ -3797,7 +3808,8 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ + info->allowColorTiling ? 2048 : + 64 * pScrn->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ 2048, /* maxHeight */ pScrn->display->virtualX, @@ -3865,7 +3877,8 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ + info->allowColorTiling ? 2048 : + 64 * pScrn->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ 2048, /* maxHeight */ pScrn->display->virtualX, @@ -4192,15 +4205,6 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) /* This option checked by the RADEON DRM kernel module */ } - /* Depth moves are disabled by default since they are extremely slow */ - if ((info->depthMoves = xf86ReturnOptValBool(info->Options, - OPTION_DEPTH_MOVE, FALSE))) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling depth moves\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Depth moves disabled by default\n"); - } - /* Two options to try and squeeze as much texture memory as possible * for dedicated 3d rendering boxes */ @@ -4568,6 +4572,25 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) "Couldn't load fbdevhw module, not using framebuffer device\n"); } } + + info->allowColorTiling = xf86ReturnOptValBool(info->Options, + OPTION_COLOR_TILING, TRUE); + if ((info->allowColorTiling) && (info->IsSecondary)) { + /* can't have tiling on the 2nd head (as long as it can't use drm). We'd never + get the surface save/restore (vt switching) right... */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled for 2nd head\n"); + info->allowColorTiling = FALSE; + } + else if ((info->allowColorTiling) && (info->FBDev)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Color tiling not supported with UseFBDev option\n"); + info->allowColorTiling = FALSE; + } + else if (info->allowColorTiling) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling enabled by default\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled\n"); + } if (!info->FBDev) if (!RADEONPreInitInt10(pScrn, &pInt10)) @@ -4851,6 +4874,36 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } + if (info->allowColorTiling && (pScrn->virtualX > 2048)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Color tiling not supported with virtual x resolutions larger than 2048, disabling\n"); + info->allowColorTiling = FALSE; + } + if (info->allowColorTiling) { + if (info->MergedFB) { + if ((((RADEONMergedDisplayModePtr)pScrn->currentMode->Private)->CRT1->Flags & + (V_DBLSCAN | V_INTERLACE)) || + (((RADEONMergedDisplayModePtr)pScrn->currentMode->Private)->CRT2->Flags & + (V_DBLSCAN | V_INTERLACE))) + info->tilingEnabled = FALSE; + else info->tilingEnabled = TRUE; + } + else { + info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; + } + } + + if (!info->IsSecondary) { + /* empty the surfaces */ + unsigned char *RADEONMMIO = info->MMIO; + unsigned int i; + for (i = 0; i < 8; i++) { + OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0); + } + } + if (info->FBDev) { unsigned char *RADEONMMIO = info->MMIO; @@ -4942,6 +4995,20 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } #endif + /* Depth moves are disabled by default since they are extremely slow */ + info->depthMoves = xf86ReturnOptValBool(info->Options, + OPTION_DEPTH_MOVE, FALSE); + if (info->depthMoves && info->allowColorTiling) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling depth moves\n"); + } else if (info->depthMoves) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Depth moves don't work without color tiling, disabled\n"); + info->depthMoves = FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Depth moves disabled by default\n"); + } + RADEONSetFBLocation(pScrn); if (!fbScreenInit(pScreen, info->FB, @@ -4993,26 +5060,32 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef XF86DRI if (info->directRenderingEnabled) { FBAreaPtr fbarea; - int width_bytes = (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes); - int cpp = info->CurrentLayout.pixel_bytes; - int bufferSize = ((pScrn->virtualY * width_bytes - + RADEON_BUFFER_ALIGN) - & ~RADEON_BUFFER_ALIGN); + 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, - * and its height a multiple of 16 lines. + * which is always the case due to color pitch and its height a multiple of 16 lines. */ - info->depthPitch = (pScrn->displayWidth + 31) & ~31; - depthSize = ((((pScrn->virtualY+15) & ~15) * info->depthPitch - * info->CurrentLayout.pixel_bytes + RADEON_BUFFER_ALIGN) - & ~RADEON_BUFFER_ALIGN); + info->depthPitch = pScrn->displayWidth; + depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch + * cpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); switch (info->CPMode) { case RADEON_DEFAULT_CP_PIO_MODE: @@ -5052,14 +5125,16 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 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 */ + /* If there's still no space for textures, try without pixmap cache, but never use + the reserved space and the space hw cursor might use */ if (info->textureSize < 0) { info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize - - 64/4*64; + - 2 * width_bytes - 16384; } /* 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 = @@ -5071,6 +5146,19 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 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; @@ -5093,10 +5181,16 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 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 + + info->textureOffset = ((info->FbMapSize - info->textureSize + RADEON_BUFFER_ALIGN) & ~(CARD32)RADEON_BUFFER_ALIGN); + } /* Reserve space for the shared depth * buffer. @@ -5108,12 +5202,10 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* Reserve space for the shared back buffer */ if (info->noBackBuffer) { info->backOffset = info->depthOffset; - info->backPitch = pScrn->displayWidth; } else { info->backOffset = ((info->depthOffset - bufferSize + RADEON_BUFFER_ALIGN) & ~(CARD32)RADEON_BUFFER_ALIGN); - info->backPitch = pScrn->displayWidth; } info->backY = info->backOffset / width_bytes; @@ -5139,9 +5231,14 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 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, - 2, 0, NULL, NULL, + 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", @@ -5194,12 +5291,11 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } else #endif { + int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; MemBox.x1 = 0; MemBox.y1 = 0; MemBox.x2 = pScrn->displayWidth; - y2 = (info->FbMapSize - / (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes)); + y2 = info->FbMapSize / width_bytes; if (y2 >= 32768) y2 = 32767; /* because MemBox.y2 is signed short */ MemBox.y2 = y2; @@ -5223,7 +5319,10 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, - 2, 0, NULL, NULL, + 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", @@ -5241,6 +5340,9 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } + info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) << 22) | + ((info->fbLocation + pScrn->fbOffset) >> 10)); + /* Acceleration setup */ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { if (RADEONAccelInit(pScreen)) { @@ -5348,11 +5450,27 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) RADEONInitDispBandwidth(pScrn); } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); + + /* we might already be in tiled mode, tell drm about it */ + if (info->directRenderingEnabled && info->tilingEnabled) { + drmRadeonSetParam radeonsetparam; + memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); + radeonsetparam.param = RADEON_SETPARAM_SWITCH_TILING; + radeonsetparam.value = info->tilingEnabled ? 1 : 0; + if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, + &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed changing tiling status\n"); + } + } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n"); } #endif + if (!info->IsSecondary) + RADEONChangeSurfaces(pScrn); + if(info->MergedFB) { /* need this here to fix up sarea values */ RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); @@ -5784,6 +5902,130 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, ~(RADEON_PIX2CLK_SRC_SEL_MASK)); } +void RADEONChangeSurfaces(ScrnInfoPtr pScrn) +{ + /* the idea here is to only set up front buffer as tiled, and back/depth buffer when needed. + Everything else is left as untiled. This means we need to use eplicit src/dst pitch control + when blitting, based on the src/target address, and can no longer use a default offset. + But OTOH we don't need to dynamically change surfaces (for xv for instance), and some + ugly offset / fb reservation (cursor) is gone. And as a bonus, everything actually works... + For simplicity, just always update everything (just let the ioctl fail - could do better). + All surface addresses are relative to RADEON_MC_FB_LOCATION */ + + RADEONInfoPtr info = RADEONPTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + /* depth/front/back pitch must be identical (and the same as displayWidth) */ + int width_bytes = pScrn->displayWidth * cpp; + int bufferSize = ((((pScrn->virtualY + 15) & ~15) * width_bytes + + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); + unsigned int depth_pattern, color_pattern, swap_pattern; + + swap_pattern = 0; +#if X_BYTE_ORDER == X_BIG_ENDIAN + switch (pScrn->bitsPerPixel) { + case 16: + swap_pattern = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; + break; + + case 32: + swap_pattern = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; + break; + } +#endif + if (info->ChipFamily < CHIP_FAMILY_R200) { + color_pattern = RADEON_SURF_TILE_COLOR_MACRO; + if (cpp == 2) + depth_pattern = RADEON_SURF_TILE_DEPTH_16BPP; + else + depth_pattern = RADEON_SURF_TILE_DEPTH_32BPP; + } + else { + /* no idea about R300, just set it up the same as r200 + if someone is crazy enough to try... */ + color_pattern = R200_SURF_TILE_COLOR_MACRO; + if (cpp == 2) + depth_pattern = R200_SURF_TILE_DEPTH_16BPP; + else + depth_pattern = R200_SURF_TILE_DEPTH_32BPP; + } +#ifdef XF86DRI + if (info->directRenderingEnabled && info->allowColorTiling) { + drmRadeonSurfaceFree drmsurffree; + int retvalue; + + drmsurffree.address = info->frontOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_FREE, + &drmsurffree, sizeof(drmsurffree)); + + if ((info->ChipFamily != CHIP_FAMILY_RV100) || + (info->ChipFamily != CHIP_FAMILY_RS100) || + (info->ChipFamily != CHIP_FAMILY_RS200)) { + drmsurffree.address = info->depthOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_FREE, + &drmsurffree, sizeof(drmsurffree)); + } + + if (!info->noBackBuffer) { + drmsurffree.address = info->backOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_FREE, + &drmsurffree, sizeof(drmsurffree)); + } + + if (info->tilingEnabled) { + drmRadeonSurfaceAlloc drmsurfalloc; + drmsurfalloc.size = bufferSize; + drmsurfalloc.address = info->frontOffset; + drmsurfalloc.flags = swap_pattern | (width_bytes / 16) | color_pattern; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, + &drmsurfalloc, sizeof(drmsurfalloc)); + if (retvalue < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm: could not allocate surface for front buffer!\n"); + + if ((info->have3DWindows) && (!info->noBackBuffer)) { + drmsurfalloc.address = info->backOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, + &drmsurfalloc, sizeof(drmsurfalloc)); + if (retvalue < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm: could not allocate surface for back buffer!\n"); + } + } + /* rv100 and probably the derivative igps don't have depth tiling on all the time? */ + if (info->have3DWindows && ((info->ChipFamily != CHIP_FAMILY_RV100) || + (info->ChipFamily != CHIP_FAMILY_RS100) || + (info->ChipFamily != CHIP_FAMILY_RS200))) { + drmRadeonSurfaceAlloc drmsurfalloc; + drmsurfalloc.size = bufferSize; + drmsurfalloc.address = info->depthOffset; + drmsurfalloc.flags = swap_pattern | (width_bytes / 16) | depth_pattern; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, + &drmsurfalloc, sizeof(drmsurfalloc)); + if (retvalue < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm: could not allocate surface for depth buffer!\n"); + } + } + else +#endif + if (info->allowColorTiling) { + unsigned int surf_info = 0; + unsigned char *RADEONMMIO = info->MMIO; + /* we don't need anything like WaitForFifo, no? */ + if (!info->IsSecondary) { + if (info->tilingEnabled) { + surf_info = swap_pattern | (width_bytes / 16) | color_pattern; + } + OUTREG(RADEON_SURFACE0_INFO, surf_info); + OUTREG(RADEON_SURFACE0_LOWER_BOUND, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND, bufferSize - 1); +/* xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "surface0 set to %x, LB 0x%x UB 0x%x\n", + surf_info, 0, bufferSize - 1024);*/ + } + } +} + #if 0 /* Write palette data */ static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) @@ -5810,6 +6052,35 @@ static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) } #endif +/* restore original surface info (for fb console). */ +static void RADEONRestoreSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned int surfnr; + + for ( surfnr = 0; surfnr < 8; surfnr++ ) { + OUTREG(RADEON_SURFACE0_INFO + 16 * surfnr, restore->surfaces[surfnr][0]); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr, restore->surfaces[surfnr][1]); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr, restore->surfaces[surfnr][2]); + } +} + +/* save original surface info (for fb console). */ +static void RADEONSaveSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned int surfnr; + + for ( surfnr = 0; surfnr < 8; surfnr++ ) { + save->surfaces[surfnr][0] = INREG(RADEON_SURFACE0_INFO + 16 * surfnr); + save->surfaces[surfnr][1] = INREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr); + save->surfaces[surfnr][2] = INREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr); + } +} + + /* Write out state to define a new video mode */ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) { @@ -6122,6 +6393,8 @@ static void RADEONSave(ScrnInfoPtr pScrn) } RADEONSaveMode(pScrn, save); + if (!info->IsSecondary) + RADEONSaveSurfaces(pScrn, save); } /* Restore the original (text) mode */ @@ -6161,6 +6434,8 @@ static void RADEONRestore(ScrnInfoPtr pScrn) #endif RADEONRestoreMode(pScrn, restore); + if (!info->IsSecondary) + RADEONRestoreSurfaces(pScrn, restore); #if 0 /* Temp fix to "solve" VT switch problems. When switching VTs on @@ -6654,6 +6929,12 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, save->crtc_offset = 0; save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); + if (info->tilingEnabled) { + save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + ((pScrn->bitsPerPixel * 8) -1)) / @@ -6833,6 +7114,12 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, */ save->crtc2_offset = 0; save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & RADEON_CRTC_OFFSET_FLIP_CNTL; + if (info->tilingEnabled) { + save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } /* this should be right */ if (info->MergedFB) { @@ -7435,6 +7722,7 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + Bool tilingOld = info->tilingEnabled; Bool ret; #ifdef XF86DRI Bool CPStarted = info->CPStarted; @@ -7445,6 +7733,35 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #endif + if (info->allowColorTiling) { + if (info->MergedFB) { + if ((((RADEONMergedDisplayModePtr)mode->Private)->CRT1->Flags & + (V_DBLSCAN | V_INTERLACE)) || + (((RADEONMergedDisplayModePtr)mode->Private)->CRT2->Flags & + (V_DBLSCAN | V_INTERLACE))) + info->tilingEnabled = FALSE; + else info->tilingEnabled = TRUE; + } + else { + info->tilingEnabled = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; + } +#ifdef XF86DRI + if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { + RADEONSAREAPrivPtr pSAREAPriv; + drmRadeonSetParam radeonsetparam; + memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); + radeonsetparam.param = RADEON_SETPARAM_SWITCH_TILING; + radeonsetparam.value = info->tilingEnabled ? 1 : 0; + if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, + &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed changing tiling status\n"); + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE; + } +#endif + } + if (info->accelOn) info->accel->Sync(pScrn); if (info->FBDev) { @@ -7459,6 +7776,14 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) info->IsSwitching = FALSE; } + if (info->tilingEnabled != tilingOld) { + /* need to redraw front buffer, I guess this can be considered a hack ? */ + xf86EnableDisableFBAccess(scrnIndex, FALSE); + RADEONChangeSurfaces(pScrn); + xf86EnableDisableFBAccess(scrnIndex, TRUE); + /* xf86SetRootClip would do, but can't access that here */ + } + if (info->accelOn) { info->accel->Sync(pScrn); RADEONEngineRestore(pScrn); @@ -7514,7 +7839,7 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int reg, Base; + int reg, Base, regcntl, crtcoffsetcntl; #ifdef XF86DRI RADEONSAREAPrivPtr pSAREAPriv; XF86DRISAREAPtr pSAREA; @@ -7528,13 +7853,43 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) y += (pScrn->virtualY - 1) * (y / 3 + 1); if (y > lastline) y = lastline; } - Base = y * info->CurrentLayout.displayWidth + x; - - switch (info->CurrentLayout.pixel_code) { - case 15: - case 16: Base *= 2; break; - case 24: Base *= 3; break; - case 32: Base *= 4; break; + + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ + if (clone || info->IsSecondary) { + regcntl = RADEON_CRTC2_OFFSET_CNTL; + } else { + regcntl = RADEON_CRTC_OFFSET_CNTL; + } + crtcoffsetcntl = INREG(regcntl) & ~0xf; + /* try to get rid of flickering when scrolling at least for 2d */ + if (!info->have3DWindows) crtcoffsetcntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; + if (info->tilingEnabled) { + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base = tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + crtcoffsetcntl = crtcoffsetcntl | (y % 16); + if (((info->ChipFamily == CHIP_FAMILY_RV100) || + (info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) && ((y >> 3) % 2)) { + /* FIXME: unknown why some cards (confirmed only for rv100) need this. + other cards might need that too (all 64bit cards maybe?) */ + Base ^= 2048; + } + } + else { + Base = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: Base *= 2; break; + case 24: Base *= 3; break; + case 32: Base *= 4; break; + } } Base &= ~7; /* 3 lower bits are always 0 */ @@ -7573,6 +7928,7 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) #endif OUTREG(reg, Base); + OUTREG(regcntl, crtcoffsetcntl); } void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) @@ -7633,6 +7989,8 @@ Bool RADEONEnterVT(int scrnIndex, int flags) if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; RADEONSetFBLocation(pScrn); + if (!info->IsSecondary) + RADEONRestoreSurfaces(pScrn, &info->ModeReg); #ifdef XF86DRI if (info->directRenderingEnabled) { /* get the Radeon back into shape after resume */ @@ -7685,6 +8043,8 @@ void RADEONLeaveVT(int scrnIndex, int flags) fbdevHWLeaveVT(scrnIndex,flags); } + if (!info->IsSecondary) + RADEONSaveSurfaces(pScrn, save); RADEONRestore(pScrn); } diff --git a/src/radeon_reg.h b/src/radeon_reg.h index cba64bb..4048fec 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -487,6 +487,10 @@ #define RADEON_DP_CNTL 0x16c0 # define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0) # define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1) +# define RADEON_DP_DST_TILE_LINEAR (0 << 3) +# define RADEON_DP_DST_TILE_MACRO (1 << 3) +# define RADEON_DP_DST_TILE_MICRO (2 << 3) +# define RADEON_DP_DST_TILE_BOTH (3 << 3) #define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 # define RADEON_DST_Y_MAJOR (1 << 2) # define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) @@ -1280,6 +1284,20 @@ # define RADEON_NONSURF_AP1_SWP_16BPP (1 << 22) # define RADEON_NONSURF_AP1_SWP_32BPP (1 << 23) #define RADEON_SURFACE0_INFO 0x0b0c +# define RADEON_SURF_TILE_COLOR_MACRO (0 << 16) +# define RADEON_SURF_TILE_COLOR_BOTH (1 << 16) +# define RADEON_SURF_TILE_DEPTH_32BPP (2 << 16) +# define RADEON_SURF_TILE_DEPTH_16BPP (3 << 16) +# define R200_SURF_TILE_NONE (0 << 16) +# define R200_SURF_TILE_COLOR_MACRO (1 << 16) +# define R200_SURF_TILE_COLOR_MICRO (2 << 16) +# define R200_SURF_TILE_COLOR_BOTH (3 << 16) +# define R200_SURF_TILE_DEPTH_32BPP (4 << 16) +# define R200_SURF_TILE_DEPTH_16BPP (5 << 16) +# define RADEON_SURF_AP0_SWP_16BPP (1 << 20) +# define RADEON_SURF_AP0_SWP_32BPP (1 << 21) +# define RADEON_SURF_AP1_SWP_16BPP (1 << 22) +# define RADEON_SURF_AP1_SWP_32BPP (1 << 23) #define RADEON_SURFACE0_LOWER_BOUND 0x0b04 #define RADEON_SURFACE0_UPPER_BOUND 0x0b08 #define RADEON_SURFACE1_INFO 0x0b1c diff --git a/src/radeon_render.c b/src/radeon_render.c index 4521c0e..f4cad67 100644 --- a/src/radeon_render.c +++ b/src/radeon_render.c @@ -551,9 +551,8 @@ FUNC_NAME(R100SetupForCPUToScreenAlphaTexture) ( srccolor = ((alpha & 0xff00) << 16) | ((red & 0xff00) << 8) | (blue >> 8) | (green & 0xff00); - BEGIN_ACCEL(8); + BEGIN_ACCEL(7); OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE); - OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth); OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); OUT_ACCEL_REG(RADEON_PP_TFACTOR_0, srccolor); @@ -600,9 +599,8 @@ FUNC_NAME(R100SetupForCPUToScreenTexture) ( colorformat = RadeonGetColorFormat(dstFormat); - BEGIN_ACCEL(7); + BEGIN_ACCEL(6); OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE); - OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth); OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); if (srcFormat != PICT_a8) @@ -640,24 +638,36 @@ FUNC_NAME(R100SubsequentCPUToScreenTexture) ( /* Note: we can't simply set up the 3D surface at the same location as the * front buffer, because the 2048x2048 limit on coordinates may be smaller * than the (MergedFB) screen. + * Can't use arbitrary offsets for color tiling */ - byteshift = (pScrn->bitsPerPixel >> 4); - fboffset = (info->fbLocation + pScrn->fbOffset + + if (info->tilingEnabled) { + /* can't play tricks with x coordinate, or could we - tiling is disabled anyway in that case */ + fboffset = info->fbLocation + pScrn->fbOffset + + (pScrn->displayWidth * (dsty & ~15) * (pScrn->bitsPerPixel >> 3)); + l = dstx; + t = (dsty % 16); + } + else { + byteshift = (pScrn->bitsPerPixel >> 4); + fboffset = (info->fbLocation + pScrn->fbOffset + ((pScrn->displayWidth * dsty + dstx) << byteshift)) & ~15; - l = ((dstx << byteshift) % 16) >> byteshift; - t = 0.0; + l = ((dstx << byteshift) % 16) >> byteshift; + t = 0.0; + } + r = width + l; - b = height; + b = height + t; fl = srcx; fr = srcx + width; ft = srcy; fb = srcy + height; #ifdef ACCEL_CP - BEGIN_RING(23); + BEGIN_RING(25); + OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth | + ((info->tilingEnabled && (dsty <= pScrn->virtualY)) ? RADEON_COLOR_TILE_ENABLE : 0)); OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset); - OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, 17)); /* RADEON_SE_VTX_FMT */ OUT_RING(RADEON_CP_VC_FRMT_XY | @@ -693,8 +703,10 @@ FUNC_NAME(R100SubsequentCPUToScreenTexture) ( ADVANCE_RING(); #else - BEGIN_ACCEL(19); + BEGIN_ACCEL(20); + OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth | + ((info->tilingEnabled && (dsty <= pScrn->virtualY)) ? RADEON_COLOR_TILE_ENABLE : 0)); OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset); OUT_ACCEL_REG(RADEON_SE_VF_CNTL, RADEON_VF_PRIM_TYPE_TRIANGLE_FAN | @@ -870,9 +882,8 @@ FUNC_NAME(R200SetupForCPUToScreenAlphaTexture) ( srccolor = ((alpha & 0xff00) << 16) | ((red & 0xff00) << 8) | (blue >> 8) | (green & 0xff00); - BEGIN_ACCEL(11); + BEGIN_ACCEL(10); OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE); - OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth); OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); OUT_ACCEL_REG(R200_PP_TFACTOR_0, srccolor); @@ -920,9 +931,8 @@ FUNC_NAME(R200SetupForCPUToScreenTexture) ( colorformat = RadeonGetColorFormat(dstFormat); - BEGIN_ACCEL(10); + BEGIN_ACCEL(9); OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE); - OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth); OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); if (srcFormat != PICT_a8) @@ -960,22 +970,35 @@ FUNC_NAME(R200SubsequentCPUToScreenTexture) ( /* Note: we can't simply set up the 3D surface at the same location as the * front buffer, because the 2048x2048 limit on coordinates may be smaller * than the (MergedFB) screen. + * Can't use arbitrary offsets for color tiling */ - byteshift = (pScrn->bitsPerPixel >> 4); - fboffset = (info->fbLocation + pScrn->fbOffset + ((pScrn->displayWidth * - dsty + dstx) << byteshift)) & ~15; - l = ((dstx << byteshift) % 16) >> byteshift; - t = 0.0; + if (info->tilingEnabled) { + /* can't play tricks with x coordinate, or could we - tiling is disabled anyway in that case */ + fboffset = info->fbLocation + pScrn->fbOffset + + (pScrn->displayWidth * (dsty & ~15) * (pScrn->bitsPerPixel >> 3)); + l = dstx; + t = (dsty % 16); + } + else { + byteshift = (pScrn->bitsPerPixel >> 4); + fboffset = (info->fbLocation + pScrn->fbOffset + + ((pScrn->displayWidth * dsty + dstx) << byteshift)) & ~15; + l = ((dstx << byteshift) % 16) >> byteshift; + t = 0.0; + } + r = width + l; - b = height; + b = height + t; fl = srcx; fr = srcx + width; ft = srcy; fb = srcy + height; #ifdef ACCEL_CP - BEGIN_RING(22); + BEGIN_RING(24); + OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth | + ((info->tilingEnabled && (dsty <= pScrn->virtualY)) ? RADEON_COLOR_TILE_ENABLE : 0)); OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset); OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2, 16)); @@ -1008,11 +1031,13 @@ FUNC_NAME(R200SubsequentCPUToScreenTexture) ( ADVANCE_RING(); #else - BEGIN_ACCEL(19); + BEGIN_ACCEL(20); /* Note: we can't simply setup 3D surface at the same location as the front buffer, some apps may draw offscreen pictures out of the limitation of radeon 3D surface. */ + OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth | + ((info->tilingEnabled && (dsty <= pScrn->virtualY)) ? RADEON_COLOR_TILE_ENABLE : 0)); OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset); OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST | diff --git a/src/radeon_sarea.h b/src/radeon_sarea.h index 556fca6..4157484 100644 --- a/src/radeon_sarea.h +++ b/src/radeon_sarea.h @@ -226,6 +226,7 @@ typedef struct { int pfAllowPageFlip; /* set by the 2d driver, read by the client */ int pfCurrentPage; /* set by kernel, read by others */ int crtc2_base; /* for pageflipping with CloneMode */ -} RADEONSAREAPriv, *RADEONSAREAPrivPtr; + int tiling_enabled; /* set by drm, read by 2d + 3d clients */ + } RADEONSAREAPriv, *RADEONSAREAPrivPtr; #endif diff --git a/src/radeon_version.h b/src/radeon_version.h index b1bca20..de91bb3 100644 --- a/src/radeon_version.h +++ b/src/radeon_version.h @@ -41,6 +41,7 @@ #define R300_DRIVER_NAME "r300" #define RADEON_VERSION_MAJOR 4 +#define RADEON_VERSION_MAJOR_TILED 5 #define RADEON_VERSION_MINOR 0 #define RADEON_VERSION_PATCH 1 |