summaryrefslogtreecommitdiff
path: root/src/radeon_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/radeon_driver.c')
-rw-r--r--src/radeon_driver.c454
1 files changed, 407 insertions, 47 deletions
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);
}