- Fix dpi when switching from clone to dualhead with MergedFB.

- Add ConstantDPI option to force a particlar dpi across mode changes Both
    based on Thomas Winischhofer's sis code.
This commit is contained in:
Alex Deucher
2006-04-01 23:02:40 +00:00
parent 607f18cfbf
commit f1ce6170ef
5 changed files with 231 additions and 107 deletions

View File

@@ -1,3 +1,15 @@
2006-04-01 Alex Deucher <agd5f@yahoo.com>
* src/radeon.h:
* src/radeon_driver.c: (RADEONPreInitModes), (RADEONPreInit),
(RADEONResetDPI), (RADEONSwitchMode):
* src/radeon_mergedfb.c: (RADEONMergedFBCalcDPI),
(RADEONMergedFBSetDpi), (RADEONMergedFBResetDpi):
* src/radeon_mergedfb.h:
- Fix dpi when switching from clone to dualhead with MergedFB.
- Add ConstantDPI option to force a particlar dpi across mode changes
Both based on Thomas Winischhofer's sis code.
2006-03-27 Benjamin Herrenschmidt <benh@kernel.crashing.org>
* src/radeon_driver.c: (RADEONRestoreMemMapRegisters),

View File

@@ -708,6 +708,11 @@ typedef struct {
Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions;
region NonRectDead, OffDead1, OffDead2;
int constantDPI; /* -1 = auto, 0 = off, 1 = on */
int RADEONDPIVX, RADEONDPIVY;
RADEONScrn2Rel MergedDPISRel;
int RADEONMergedDPIVX, RADEONMergedDPIVY, RADEONMergedDPIRot;
/* special handlings for DELL triple-head server */
Bool IsDellServer;

View File

@@ -1,5 +1,5 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.117 2004/02/19 22:38:12 tsi Exp $ */
/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.108 2006/03/23 01:37:15 benh Exp $ */
/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.109 2006-03-27 06:12:57 benh Exp $ */
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
* VA Linux Systems Inc., Fremont, California.
@@ -200,7 +200,8 @@ typedef enum {
OPTION_VGA_ACCESS,
OPTION_REVERSE_DDC,
OPTION_LVDS_PROBE_PLL,
OPTION_ACCELMETHOD
OPTION_ACCELMETHOD,
OPTION_CONSTANTDPI
} RADEONOpts;
static const OptionInfoRec RADEONOptions[] = {
@@ -264,6 +265,7 @@ static const OptionInfoRec RADEONOptions[] = {
{ OPTION_REVERSE_DDC, "ReverseDDC", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
{ OPTION_CONSTANTDPI, "ConstantDPI", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -4359,10 +4361,13 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
/* Set DPI */
/* xf86SetDpi(pScrn, 0, 0); */
if(info->MergedFB)
if (info->MergedFB) {
RADEONMergedFBSetDpi(pScrn, info->CRT2pScrn, info->CRT2Position);
else
} else {
xf86SetDpi(pScrn, 0, 0);
info->RADEONDPIVX = pScrn->virtualX;
info->RADEONDPIVY = pScrn->virtualY;
}
/* Get ScreenInit function */
if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
@@ -4822,7 +4827,7 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
const char *s;
char* microc_path = NULL;
char* microc_type = NULL;
MessageType from;
RADEONTRACE(("RADEONPreInit\n"));
if (pScrn->numEntities != 1) return FALSE;
@@ -5062,6 +5067,25 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
info->DispPriority = 1;
}
info->constantDPI = -1;
from = X_DEFAULT;
if (xf86GetOptValBool(info->Options, OPTION_CONSTANTDPI, &info->constantDPI)) {
from = X_CONFIG;
} else {
if (monitorResolution > 0) {
info->constantDPI = TRUE;
from = X_CMDLINE;
xf86DrvMsg(pScrn->scrnIndex, from,
"\"-dpi %d\" given in command line, assuming \"ConstantDPI\" set\n",
monitorResolution);
} else {
info->constantDPI = FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from,
"X server will %skeep DPI constant for all screen sizes\n",
info->constantDPI ? "" : "not ");
if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) {
/* check for Linux framebuffer device */
@@ -8656,6 +8680,26 @@ static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode)
return TRUE;
}
static void
RADEONResetDPI(ScrnInfoPtr pScrn, Bool force)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
if(force ||
(info->RADEONDPIVX != pScrn->virtualX) ||
(info->RADEONDPIVY != pScrn->virtualY)
) {
pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10);
pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10);
info->RADEONDPIVX = pScrn->virtualX;
info->RADEONDPIVY = pScrn->virtualY;
}
}
_X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
@@ -8740,8 +8784,11 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
/* Since RandR (indirectly) uses SwitchMode(), we need to
* update our Xinerama info here, too, in case of resizing
*/
if(info->MergedFB) {
RADEONUpdateXineramaScreenInfo(pScrn);
if (info->MergedFB) {
RADEONMergedFBResetDpi(pScrn, FALSE);
RADEONUpdateXineramaScreenInfo(pScrn);
} else if(info->constantDPI) {
RADEONResetDPI(pScrn, FALSE);
}
return ret;

View File

@@ -1741,119 +1741,125 @@ RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags)
RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE);
}
void
RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel)
static void
RADEONMergedFBCalcDPI(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel, Bool quiet)
{
RADEONInfoPtr info = RADEONPTR(pScrn1);
MessageType from = X_DEFAULT;
xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC);
xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC);
int ddcWidthmm = 0, ddcHeightmm = 0;
const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n";
RADEONInfoPtr info = RADEONPTR(pScrn1);
MessageType from = X_DEFAULT;
xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC);
xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC);
int ddcWidthmm = 0, ddcHeightmm = 0;
const char *dsstr = "MergedFB: Display dimensions: %dx%d mm\n";
/* This sets the DPI for MergedFB mode. The problem is that
* this can never be exact, because the output devices may
* have different dimensions. This function tries to compromise
* through a few assumptions, and it just calculates an average DPI
* value for both monitors.
*/
/* This sets the DPI for MergedFB mode. The problem is that
* this can never be exact, because the output devices may
* have different dimensions. This function tries to compromise
* through a few assumptions, and it just calculates an average
* DPI value for both monitors.
*/
/* Given DisplaySize should regard BOTH monitors */
pScrn1->widthmm = pScrn1->monitor->widthmm;
pScrn1->heightmm = pScrn1->monitor->heightmm;
/* Copy user-given DisplaySize (which should regard BOTH monitors!) */
pScrn1->widthmm = pScrn1->monitor->widthmm;
pScrn1->heightmm = pScrn1->monitor->heightmm;
/* Get DDC display size; if only either CRT1 or CRT2 provided these,
* assume equal dimensions for both, otherwise add dimensions
*/
if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) &&
(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) {
ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10;
ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10;
switch(srel) {
case radeonLeftOf:
case radeonRightOf:
ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10;
break;
case radeonAbove:
case radeonBelow:
ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10;
default:
break;
}
if(monitorResolution > 0) {
} else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) {
ddcWidthmm = DDC1->features.hsize * 10;
ddcHeightmm = DDC1->features.vsize * 10;
switch(srel) {
case radeonLeftOf:
case radeonRightOf:
ddcWidthmm *= 2;
break;
case radeonAbove:
case radeonBelow:
ddcHeightmm *= 2;
default:
break;
}
} else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) {
ddcWidthmm = DDC2->features.hsize * 10;
ddcHeightmm = DDC2->features.vsize * 10;
switch(srel) {
case radeonLeftOf:
case radeonRightOf:
ddcWidthmm *= 2;
break;
case radeonAbove:
case radeonBelow:
ddcHeightmm *= 2;
default:
break;
}
}
/* Set command line given values (overrules given options) */
pScrn1->xDpi = monitorResolution;
pScrn1->yDpi = monitorResolution;
from = X_CMDLINE;
if(monitorResolution > 0) {
} else if(info->MergedFBXDPI) {
/* Set command line given values (overrules given options) */
pScrn1->xDpi = monitorResolution;
pScrn1->yDpi = monitorResolution;
from = X_CMDLINE;
/* Set option-wise given values (overrules DisplaySize config option) */
pScrn1->xDpi = info->MergedFBXDPI;
pScrn1->yDpi = info->MergedFBYDPI;
from = X_CONFIG;
} else if(info->MergedFBXDPI) {
} else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) {
/* Set option-wise given values (overrule DisplaySize) */
pScrn1->xDpi = info->MergedFBXDPI;
pScrn1->yDpi = info->MergedFBYDPI;
from = X_CONFIG;
} else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) {
/* Set values calculated from given DisplaySize */
from = X_CONFIG;
if(pScrn1->widthmm > 0) {
pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
}
if(pScrn1->heightmm > 0) {
pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
}
xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm);
/* Set values calculated from given DisplaySize */
from = X_CONFIG;
if(pScrn1->widthmm > 0) {
pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
}
if(pScrn1->heightmm > 0) {
pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
}
if(!quiet) {
xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm);
}
} else if(ddcWidthmm && ddcHeightmm) {
/* Set values from DDC-provided display size */
from = X_PROBED;
xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm );
pScrn1->widthmm = ddcWidthmm;
pScrn1->heightmm = ddcHeightmm;
if(pScrn1->widthmm > 0) {
pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
}
if(pScrn1->heightmm > 0) {
pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
}
/* Set values from DDC-provided display size */
/* Get DDC display size; if only either CRT1 or CRT2 provided these,
* assume equal dimensions for both, otherwise add dimensions
*/
if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) &&
(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) {
ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10;
ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10;
switch(srel) {
case radeonLeftOf:
case radeonRightOf:
ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10;
break;
case radeonAbove:
case radeonBelow:
ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10;
default:
break;
}
} else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) {
ddcWidthmm = DDC1->features.hsize * 10;
ddcHeightmm = DDC1->features.vsize * 10;
switch(srel) {
case radeonLeftOf:
case radeonRightOf:
ddcWidthmm *= 2;
break;
case radeonAbove:
case radeonBelow:
ddcHeightmm *= 2;
default:
break;
}
} else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) {
ddcWidthmm = DDC2->features.hsize * 10;
ddcHeightmm = DDC2->features.vsize * 10;
switch(srel) {
case radeonLeftOf:
case radeonRightOf:
ddcWidthmm *= 2;
break;
case radeonAbove:
case radeonBelow:
ddcHeightmm *= 2;
default:
break;
}
}
from = X_PROBED;
if(!quiet) {
xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm);
}
pScrn1->widthmm = ddcWidthmm;
pScrn1->heightmm = ddcHeightmm;
if(pScrn1->widthmm > 0) {
pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
}
if(pScrn1->heightmm > 0) {
pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
}
} else {
pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI;
pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI;
}
@@ -1866,8 +1872,60 @@ RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel
pScrn2->xDpi = pScrn1->xDpi;
pScrn2->yDpi = pScrn1->yDpi;
xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n",
pScrn1->xDpi, pScrn1->yDpi);
if(!quiet) {
xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n",
pScrn1->xDpi, pScrn1->yDpi);
}
}
void
RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel)
{
RADEONInfoPtr info = RADEONPTR(pScrn1);
RADEONMergedFBCalcDPI(pScrn1, pScrn2, srel, FALSE);
info->MergedDPISRel = srel;
info->RADEONMergedDPIVX = pScrn1->virtualX;
info->RADEONMergedDPIVY = pScrn1->virtualY;
}
void
RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position;
/* This does the same calculation for the DPI as
* the initial run. This means that an eventually
* given -dpi command line switch will lead to
* constant dpi values, regardless of the virtual
* screen size.
* I consider this consequent. If this is undesired,
* one should use the DisplaySize parameter in the
* config file instead of the command line switch.
* The DPI will be calculated then.
*/
if(force ||
(info->MergedDPISRel != srel) ||
(info->RADEONMergedDPIVX != pScrn->virtualX) ||
(info->RADEONMergedDPIVY != pScrn->virtualY)
) {
RADEONMergedFBCalcDPI(pScrn, info->CRT2pScrn, srel, TRUE);
pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10);
pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10);
info->MergedDPISRel = srel;
info->RADEONMergedDPIVX = pScrn->virtualX;
info->RADEONMergedDPIVY = pScrn->virtualY;
}
}
/* radeon cursor helpers */

View File

@@ -107,6 +107,8 @@ RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1);
extern void
RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel);
extern void
RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force);
extern void
RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn);
/* needed by radeon_cursor.c */