Eliminate RRModeRec devPrivate field.

The xf86 mode setting code was mis-using this field to try and store a
pointer to a DisplayModeRec, however, each output has its own copy of every
DisplayModeRec leaving the one in in the RRModeRec devPrivate field pointing
at a random DisplayModeRec.

Instead of attempting to rectify this, eliminating the devPrivate entirely
turned out to be very easy; the DDX code now accepts an arbitrary RRModeRec
structure and set that to the hardware, converting it on the fly to a
DisplayModeRec as needed.
(cherry picked from commit 3506b9376c)
This commit is contained in:
Keith Packard 2007-02-20 23:04:26 -08:00 committed by Keith Packard
parent 2c93083edd
commit 9d0c3b52f2
2 changed files with 103 additions and 45 deletions

View File

@ -556,6 +556,56 @@ xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
}
#if RANDR_12_INTERFACE
#define FLAG_BITS (RR_HSyncPositive | \
RR_HSyncNegative | \
RR_VSyncPositive | \
RR_VSyncNegative | \
RR_Interlace | \
RR_DoubleScan | \
RR_CSync | \
RR_CSyncPositive | \
RR_CSyncNegative | \
RR_HSkewPresent | \
RR_BCast | \
RR_PixelMultiplex | \
RR_DoubleClock | \
RR_ClockDivideBy2)
static Bool
xf86RandRModeMatches (RRModePtr randr_mode,
DisplayModePtr mode)
{
#if 0
if (match_name)
{
/* check for same name */
int len = strlen (mode->name);
if (randr_mode->mode.nameLength != len) return FALSE;
if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE;
}
#endif
/* check for same timings */
if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE;
if (randr_mode->mode.width != mode->HDisplay) return FALSE;
if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE;
if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE;
if (randr_mode->mode.hTotal != mode->HTotal) return FALSE;
if (randr_mode->mode.hSkew != mode->HSkew) return FALSE;
if (randr_mode->mode.height != mode->VDisplay) return FALSE;
if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE;
if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE;
if (randr_mode->mode.vTotal != mode->VTotal) return FALSE;
/* check for same flags (using only the XF86 valid flag bits) */
if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS))
return FALSE;
/* everything matches */
return TRUE;
}
static Bool
xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
{
@ -594,12 +644,15 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
* We make copies of modes, so pointer equality
* isn't sufficient
*/
for (j = 0; j < randr_output->numModes; j++)
for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++)
{
DisplayModePtr outMode = randr_output->modes[j]->devPrivate;
if (xf86ModesEqual(mode, outMode))
RRModePtr m = (j < randr_output->numModes ?
randr_output->modes[j] :
randr_output->userModes[j-randr_output->numModes]);
if (xf86RandRModeMatches (m, mode))
{
randr_mode = randr_output->modes[j];
randr_mode = m;
break;
}
}
@ -611,6 +664,39 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
return ret;
}
/*
* Convert a RandR mode to a DisplayMode
*/
static void
xf86RandRModeConvert (ScrnInfoPtr scrn,
RRModePtr randr_mode,
DisplayModePtr mode)
{
mode->prev = NULL;
mode->next = NULL;
mode->name = NULL;
mode->status = MODE_OK;
mode->type = 0;
mode->Clock = randr_mode->mode.dotClock / 1000;
mode->HDisplay = randr_mode->mode.width;
mode->HSyncStart = randr_mode->mode.hSyncStart;
mode->HSyncEnd = randr_mode->mode.hSyncEnd;
mode->HTotal = randr_mode->mode.hTotal;
mode->HSkew = randr_mode->mode.hSkew;
mode->VDisplay = randr_mode->mode.height;
mode->VSyncStart = randr_mode->mode.vSyncStart;
mode->VSyncEnd = randr_mode->mode.vSyncEnd;
mode->VTotal = randr_mode->mode.vTotal;
mode->VScan = 0;
mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS;
xf86SetModeCrtc (mode, scrn->adjustFlags);
}
static Bool
xf86RandR12CrtcSet (ScreenPtr pScreen,
RRCrtcPtr randr_crtc,
@ -624,16 +710,15 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
xf86CrtcPtr crtc = randr_crtc->devPrivate;
DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL;
Bool changed = FALSE;
int o, ro;
xf86CrtcPtr *save_crtcs;
Bool save_enabled = crtc->enabled;
save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
if ((mode != NULL) != crtc->enabled)
if ((randr_mode != NULL) != crtc->enabled)
changed = TRUE;
else if (mode && !xf86ModesEqual (&crtc->mode, mode))
else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
changed = TRUE;
if (rotation != crtc->rotation)
@ -667,11 +752,14 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
/* XXX need device-independent mode setting code through an API */
if (changed)
{
crtc->enabled = mode != NULL;
crtc->enabled = randr_mode != NULL;
if (mode)
if (randr_mode)
{
if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
DisplayModeRec mode;
xf86RandRModeConvert (pScrn, randr_mode, &mode);
if (!xf86CrtcSetMode (crtc, &mode, rotation, x, y))
{
crtc->enabled = save_enabled;
for (o = 0; o < config->num_output; o++)
@ -685,7 +773,7 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
/*
* Save the last successful setting for EnterVT
*/
crtc->desiredMode = *mode;
crtc->desiredMode = mode;
crtc->desiredRotation = rotation;
crtc->desiredX = x;
crtc->desiredY = y;
@ -733,33 +821,12 @@ xf86RandR12OutputValidateMode (ScreenPtr pScreen,
RROutputPtr randr_output,
RRModePtr randr_mode)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86OutputPtr output = randr_output->devPrivate;
DisplayModePtr mode = randr_mode->devPrivate;
DisplayModeRec mode;
if (!mode)
{
mode = xalloc (sizeof (DisplayModeRec) + randr_mode->mode.nameLength + 1);
if (!mode)
return FALSE;
mode->name = (char *) mode + 1;
memcpy (mode->name, randr_mode->name, randr_mode->mode.nameLength);
mode->name[randr_mode->mode.nameLength] = '\0';
mode->Clock = randr_mode->mode.dotClock / 1000;
mode->HDisplay = randr_mode->mode.width;
mode->HSyncStart = randr_mode->mode.hSyncStart;
mode->HSyncEnd = randr_mode->mode.hSyncEnd;
mode->HTotal = randr_mode->mode.hTotal;
mode->HSkew = randr_mode->mode.hSkew;
mode->VDisplay = randr_mode->mode.height;
mode->VSyncStart = randr_mode->mode.vSyncStart;
mode->VSyncEnd = randr_mode->mode.vSyncEnd;
mode->VTotal = randr_mode->mode.vTotal;
mode->Flags = randr_mode->mode.modeFlags;
randr_mode->devPrivate = mode;
}
if (!output->funcs->mode_valid (output, mode))
xf86RandRModeConvert (pScrn, randr_mode, &mode);
if (output->funcs->mode_valid (output, &mode) != MODE_OK)
return FALSE;
return TRUE;
}
@ -767,13 +834,6 @@ xf86RandR12OutputValidateMode (ScreenPtr pScreen,
static void
xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode)
{
DisplayModePtr mode = randr_mode->devPrivate;
if (mode)
{
xfree (mode);
randr_mode->devPrivate = NULL;
}
}
/**
@ -822,7 +882,6 @@ xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
rrmode = RRModeGet (&modeInfo, mode->name);
if (rrmode) {
rrmode->devPrivate = mode;
rrmodes[nmode++] = rrmode;
npreferred += pref;
}

View File

@ -79,7 +79,6 @@ struct _rrMode {
int refcnt;
xRRModeInfo mode;
char *name;
void *devPrivate;
ScreenPtr userScreen;
};