diff options
author | Alan Hourihane <alanh@vmware.com> | 2011-02-16 18:53:14 +0100 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-02-16 19:50:34 +0100 |
commit | c208a5380b20f910ab49433abc0d39dce6bb5528 (patch) | |
tree | bfe141474fb0b4dc77d991380068eb2f9c4597fb /src | |
parent | 2e5001b7e93c63c2cd25d7d8ebdee8a420c13b96 (diff) |
vmwlegacy: Fix mode lookup
In situations where we have trouble finding a specified mode,
use the resolution given by the width and height device registers.
Signed-off-by: Alan Hourihane <alanh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/vmware.c | 52 | ||||
-rw-r--r-- | src/vmware.h | 4 | ||||
-rw-r--r-- | src/vmwaremodes.c | 33 |
3 files changed, 84 insertions, 5 deletions
diff --git a/src/vmware.c b/src/vmware.c index 3177138..795ad08 100644 --- a/src/vmware.c +++ b/src/vmware.c @@ -607,6 +607,7 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) int i; ClockRange* clockRanges; IOADDRESS domainIOBase = 0; + uint32 width = 0, height = 0; #ifndef BUILD_FOR_420 domainIOBase = pScrn->domainIOBase; @@ -950,17 +951,31 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) clockRanges->ClockMulFactor = 1; clockRanges->ClockDivFactor = 1; + /* Read the configured registers for an initial mode. + * This gives the benefit that at initial bootup, we're most likely + * to have an 800x600 mode and thus we have a reasonable default at + * power on. Subsequent logouts will use the pre-configured mode from + * last session which is a more natural thing. + * + * But, only if we haven't any modes specified in the config file. + */ + if (pScrn->display && pScrn->display->modes) { + width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); + height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); + } + /* * Get the default supported modelines */ - vmwareGetSupportedModelines(&pScrn->monitor->Modes); + vmwareGetSupportedModelines(pScrn, width, height); i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, NULL, 256, pVMWARE->maxWidth, 32 * 32, 128, pVMWARE->maxHeight, pScrn->display->virtualX, pScrn->display->virtualY, pVMWARE->videoRam, - LOOKUP_BEST_REFRESH); + LOOKUP_BEST_REFRESH | LOOKUP_OPTIONAL_TOLERANCES); + if (i == -1) { VMWAREFreeRec(pScrn); return FALSE; @@ -972,7 +987,38 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); - pScrn->currentMode = pScrn->modes; + + /* Walk the mode list and choose one that matches our registers */ + { + DisplayModePtr modes = pScrn->modes; + while (modes) { + if (modes->type != M_T_USERDEF) { + /* The first mode isn't our specified one, so fallback + * to a sane default so we don't get a large virtual + * screen that may be scaled to a very small initial + * login screen. + * We read the current SVGA registers, so we'll either + * end up with a default 800x600 at bootup, or the last + * virtual autofitted resolution from the previous session. + */ + width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); + height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); + } + + if (modes->HDisplay == width && modes->VDisplay == height) + break; + + modes = modes->next; + + if (modes == pScrn->modes) + break; + } + + pScrn->currentMode = modes; + pScrn->virtualX = modes->HDisplay; + pScrn->virtualY = modes->VDisplay; + } + xf86PrintModes(pScrn); xf86SetDpi(pScrn, 0, 0); if (!xf86LoadSubModule(pScrn, "fb") || diff --git a/src/vmware.h b/src/vmware.h index 9216dcd..3253a64 100644 --- a/src/vmware.h +++ b/src/vmware.h @@ -314,6 +314,8 @@ void vmwareCheckVideoSanity( /* vmwaremode.c */ void vmwareGetSupportedModelines( - DisplayModePtr *monitorModes + ScrnInfoPtr pScrn, + uint32 dwidth, + uint32 dheight ); #endif diff --git a/src/vmwaremodes.c b/src/vmwaremodes.c index 2f1e5b4..ceeedf6 100644 --- a/src/vmwaremodes.c +++ b/src/vmwaremodes.c @@ -42,6 +42,7 @@ #ifdef HAVE_XORG_SERVER_1_2_0 #include <xf86Modes.h> #endif +#include "vm_basic_types.h" #ifndef M_T_DRIVER # define M_T_DRIVER 0x40 /* Supplied by the driver (EDID, etc) */ @@ -109,9 +110,13 @@ static DisplayModeRec VMwareModes[] = { */ void -vmwareGetSupportedModelines(DisplayModePtr *monitorModes) +vmwareGetSupportedModelines(ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight) { + MonPtr monitor = pScrn->monitor; + DisplayModePtr *monitorModes = &pScrn->monitor->Modes; DisplayModePtr modes = NULL, mode = NULL; + DisplayModeRec dynamic = + { MODEPREFIX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX }; int i = 0; if (monitorModes == NULL || *monitorModes == NULL) { @@ -124,6 +129,32 @@ vmwareGetSupportedModelines(DisplayModePtr *monitorModes) modes = xf86ModesAdd(modes, mode); } + /* + * Let's add a mode of current SVGA register values and so we can + * match against this for subsequent login. + */ + if (dwidth && dheight) { + dynamic.HDisplay = dwidth; + dynamic.HSyncStart = dynamic.HDisplay + 1; + dynamic.HSyncEnd = dynamic.HSyncStart + 1; + dynamic.HTotal = dynamic.HSyncEnd * 5 / 4; + if (monitor->nHsync > 0) + dynamic.Clock = dynamic.HTotal * monitor->hsync[0].lo; + else + dynamic.Clock = 75000; + dynamic.VDisplay = dheight; + dynamic.VSyncStart = dynamic.VDisplay + 1; + dynamic.VSyncEnd = dynamic.VSyncStart + 1; + dynamic.VTotal = dynamic.VSyncEnd + 1; + if (monitor->nVrefresh > 0) + dynamic.VRefresh = monitor->vrefresh[0].lo; + else + dynamic.VRefresh = 60000; + + mode = xf86DuplicateMode(&dynamic); + modes = xf86ModesAdd(modes, mode); + } + *monitorModes = xf86ModesAdd(*monitorModes, modes); #endif } |