diff options
author | Roland Scheidegger <rscheidegger_lists@hispeed.ch> | 2005-01-26 18:23:41 +0000 |
---|---|---|
committer | Roland Scheidegger <rscheidegger_lists@hispeed.ch> | 2005-01-26 18:23:41 +0000 |
commit | a2b123f7672ea678290798786ecb408a86d8c683 (patch) | |
tree | b3ee76a2664b7156875b5abb4891d0499e56994a /src | |
parent | e0df1e41724cd009fe7c833d2f9555f5d87e3202 (diff) |
(Stephane Marchesin, me) Add support for color (framebuffer) tiling.
Convert all XAA accel code to use explicit dst and src offset pitch
control to make it work. Use the new drm surface ioctls to set up the
tiled surfaces (if dri is enabled).
Diffstat (limited to 'src')
-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 |
10 files changed, 599 insertions, 204 deletions
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 |