summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/radeon.man14
-rw-r--r--src/radeon.h6
-rw-r--r--src/radeon_accel.c9
-rw-r--r--src/radeon_accelfuncs.c99
-rw-r--r--src/radeon_common.h17
-rw-r--r--src/radeon_dri.c123
-rw-r--r--src/radeon_driver.c454
-rw-r--r--src/radeon_reg.h18
-rw-r--r--src/radeon_render.c73
-rw-r--r--src/radeon_sarea.h3
-rw-r--r--src/radeon_version.h1
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