Add support for user-defined modelines in RandR.

The RandR protocol spec has several requests in support of user-defined
modes, but the implementation was stubbed out inside the X server. Fill out
the DIX portion and start on the xf86 DDX portion. It might be necessary to
add more code to the DDX to insert the user-defined modes into the output
mode list.
(cherry picked from commit 63cc2a51ef87130c632a874672a8c9167f14314e)

Conflicts:

	randr/randrstr.h

Updated code to work in master with recent security API changes.
This commit is contained in:
Keith Packard 2007-02-18 23:49:38 -08:00 committed by Keith Packard
parent 3bffb28126
commit 2c93083edd
8 changed files with 400 additions and 50 deletions

View File

@ -728,6 +728,54 @@ xf86RandR12OutputSetProperty (ScreenPtr pScreen,
return output->funcs->set_property(output, property, value); return output->funcs->set_property(output, property, value);
} }
static Bool
xf86RandR12OutputValidateMode (ScreenPtr pScreen,
RROutputPtr randr_output,
RRModePtr randr_mode)
{
xf86OutputPtr output = randr_output->devPrivate;
DisplayModePtr mode = randr_mode->devPrivate;
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))
return FALSE;
return TRUE;
}
static void
xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode)
{
DisplayModePtr mode = randr_mode->devPrivate;
if (mode)
{
xfree (mode);
randr_mode->devPrivate = NULL;
}
}
/** /**
* Given a list of xf86 modes and a RandR Output object, construct * Given a list of xf86 modes and a RandR Output object, construct
* RandR modes and assign them to the output * RandR modes and assign them to the output
@ -958,6 +1006,8 @@ xf86RandR12Init12 (ScreenPtr pScreen)
rp->rrCrtcSet = xf86RandR12CrtcSet; rp->rrCrtcSet = xf86RandR12CrtcSet;
rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
rp->rrOutputSetProperty = xf86RandR12OutputSetProperty; rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
rp->rrModeDestroy = xf86RandR12ModeDestroy;
rp->rrSetConfig = NULL; rp->rrSetConfig = NULL;
pScrn->PointerMoved = xf86RandR12PointerMoved; pScrn->PointerMoved = xf86RandR12PointerMoved;
if (!xf86RandR12CreateObjects12 (pScreen)) if (!xf86RandR12CreateObjects12 (pScreen))

View File

@ -73,6 +73,20 @@ miRROutputSetProperty (ScreenPtr pScreen,
return TRUE; return TRUE;
} }
Bool
miRROutputValidateMode (ScreenPtr pScreen,
RROutputPtr output,
RRModePtr mode)
{
return FALSE;
}
void
miRRModeDestroy (ScreenPtr pScreen,
RRModePtr mode)
{
}
/* /*
* This function assumes that only a single depth can be * This function assumes that only a single depth can be
* displayed at a time, but that all visuals of that depth * displayed at a time, but that all visuals of that depth
@ -102,7 +116,8 @@ miRandRInit (ScreenPtr pScreen)
pScrPriv->rrCrtcSet = miRRCrtcSet; pScrPriv->rrCrtcSet = miRRCrtcSet;
pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma; pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma;
pScrPriv->rrOutputSetProperty = miRROutputSetProperty; pScrPriv->rrOutputSetProperty = miRROutputSetProperty;
pScrPriv->rrOutputValidateMode = miRROutputValidateMode;
pScrPriv->rrModeDestroy = miRRModeDestroy;
RRScreenSetSizeRange (pScreen, RRScreenSetSizeRange (pScreen,
pScreen->width, pScreen->height, pScreen->width, pScreen->height,

View File

@ -80,7 +80,7 @@ struct _rrMode {
xRRModeInfo mode; xRRModeInfo mode;
char *name; char *name;
void *devPrivate; void *devPrivate;
Bool userDefined; ScreenPtr userScreen;
}; };
struct _rrPropertyValue { struct _rrPropertyValue {
@ -135,6 +135,8 @@ struct _rrOutput {
int numModes; int numModes;
int numPreferred; int numPreferred;
RRModePtr *modes; RRModePtr *modes;
int numUserModes;
RRModePtr *userModes;
Bool changed; Bool changed;
RRPropertyPtr properties; RRPropertyPtr properties;
void *devPrivate; void *devPrivate;
@ -164,6 +166,13 @@ typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen,
Atom property, Atom property,
RRPropertyValuePtr value); RRPropertyValuePtr value);
typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen,
RROutputPtr output,
RRModePtr mode);
typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen,
RRModePtr mode);
#endif #endif
typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations); typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
@ -208,6 +217,8 @@ typedef struct _rrScrPriv {
RRCrtcSetProcPtr rrCrtcSet; RRCrtcSetProcPtr rrCrtcSet;
RRCrtcSetGammaProcPtr rrCrtcSetGamma; RRCrtcSetGammaProcPtr rrCrtcSetGamma;
RROutputSetPropertyProcPtr rrOutputSetProperty; RROutputSetPropertyProcPtr rrOutputSetProperty;
RROutputValidateModeProcPtr rrOutputValidateMode;
RRModeDestroyProcPtr rrModeDestroy;
#endif #endif
/* /*
@ -394,6 +405,15 @@ miRROutputSetProperty (ScreenPtr pScreen,
Atom property, Atom property,
RRPropertyValuePtr value); RRPropertyValuePtr value);
Bool
miRROutputValidateMode (ScreenPtr pScreen,
RROutputPtr output,
RRModePtr mode);
void
miRRModeDestroy (ScreenPtr pScreen,
RRModePtr mode);
/* randr.c */ /* randr.c */
/* /*
* Send all pending events * Send all pending events
@ -549,6 +569,11 @@ Bool
RRCrtcSetRotations (RRCrtcPtr crtc, RRCrtcSetRotations (RRCrtcPtr crtc,
Rotation rotations); Rotation rotations);
/*
* Return the area of the frame buffer scanned out by the crtc,
* taking into account the current mode and rotation
*/
void void
RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
@ -672,6 +697,14 @@ RROutputSetModes (RROutputPtr output,
int numModes, int numModes,
int numPreferred); int numPreferred);
int
RROutputAddUserMode (RROutputPtr output,
RRModePtr mode);
int
RROutputDeleteUserMode (RROutputPtr output,
RRModePtr mode);
Bool Bool
RROutputSetCrtcs (RROutputPtr output, RROutputSetCrtcs (RROutputPtr output,
RRCrtcPtr *crtcs, RRCrtcPtr *crtcs,

View File

@ -666,10 +666,15 @@ ProcRRSetCrtcConfig (ClientPtr client)
return BadMatch; return BadMatch;
} }
/* validate mode for this output */ /* validate mode for this output */
for (j = 0; j < outputs[i]->numModes; j++) for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
if (outputs[i]->modes[j] == mode) {
RRModePtr m = (j < outputs[i]->numModes ?
outputs[i]->modes[j] :
outputs[i]->userModes[j - outputs[i]->numModes]);
if (m == mode)
break; break;
if (j == outputs[i]->numModes) }
if (j == outputs[i]->numModes + outputs[i]->numUserModes)
{ {
if (outputs) if (outputs)
xfree (outputs); xfree (outputs);

View File

@ -157,9 +157,11 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
pScrPriv->nSizes = 0; pScrPriv->nSizes = 0;
/* find size bounds */ /* find size bounds */
for (i = 0; i < output->numModes; i++) for (i = 0; i < output->numModes + output->numUserModes; i++)
{ {
RRModePtr mode = output->modes[i]; RRModePtr mode = (i < output->numModes ?
output->modes[i] :
output->userModes[i-output->numModes]);
CARD16 width = mode->mode.width; CARD16 width = mode->mode.width;
CARD16 height = mode->mode.height; CARD16 height = mode->mode.height;

View File

@ -48,25 +48,13 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo *b)
static int num_modes; static int num_modes;
static RRModePtr *modes; static RRModePtr *modes;
RRModePtr static RRModePtr
RRModeGet (xRRModeInfo *modeInfo, RRModeCreate (xRRModeInfo *modeInfo,
const char *name) const char *name,
ScreenPtr userScreen)
{ {
int i; RRModePtr mode, *newModes;
RRModePtr mode;
RRModePtr *newModes;
for (i = 0; i < num_modes; i++)
{
mode = modes[i];
if (RRModeEqual (&mode->mode, modeInfo) &&
!memcmp (name, mode->name, modeInfo->nameLength))
{
++mode->refcnt;
return mode;
}
}
if (!RRInit ()) if (!RRInit ())
return NULL; return NULL;
@ -78,7 +66,7 @@ RRModeGet (xRRModeInfo *modeInfo,
mode->name = (char *) (mode + 1); mode->name = (char *) (mode + 1);
memcpy (mode->name, name, modeInfo->nameLength); memcpy (mode->name, name, modeInfo->nameLength);
mode->name[modeInfo->nameLength] = '\0'; mode->name[modeInfo->nameLength] = '\0';
mode->userDefined = FALSE; mode->userScreen = userScreen;
if (num_modes) if (num_modes)
newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr)); newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr));
@ -104,11 +92,75 @@ RRModeGet (xRRModeInfo *modeInfo,
return mode; return mode;
} }
static RRModePtr
RRModeFindByName (const char *name,
CARD16 nameLength)
{
int i;
RRModePtr mode;
for (i = 0; i < num_modes; i++)
{
mode = modes[i];
if (mode->mode.nameLength == nameLength &&
!memcmp (name, mode->name, nameLength))
{
return mode;
}
}
return NULL;
}
RRModePtr
RRModeGet (xRRModeInfo *modeInfo,
const char *name)
{
int i;
for (i = 0; i < num_modes; i++)
{
RRModePtr mode = modes[i];
if (RRModeEqual (&mode->mode, modeInfo) &&
!memcmp (name, mode->name, modeInfo->nameLength))
{
++mode->refcnt;
return mode;
}
}
return RRModeCreate (modeInfo, name, NULL);
}
static RRModePtr
RRModeCreateUser (ScreenPtr pScreen,
xRRModeInfo *modeInfo,
const char *name,
int *error)
{
RRModePtr mode;
mode = RRModeFindByName (name, modeInfo->nameLength);
if (mode)
{
*error = BadName;
return NULL;
}
mode = RRModeCreate (modeInfo, name, pScreen);
if (!mode)
{
*error = BadAlloc;
return NULL;
}
*error = Success;
return mode;
}
RRModePtr * RRModePtr *
RRModesForScreen (ScreenPtr pScreen, int *num_ret) RRModesForScreen (ScreenPtr pScreen, int *num_ret)
{ {
rrScrPriv(pScreen); rrScrPriv(pScreen);
int o, c; int o, c, m;
RRModePtr *screen_modes; RRModePtr *screen_modes;
int num_screen_modes = 0; int num_screen_modes = 0;
@ -122,9 +174,11 @@ RRModesForScreen (ScreenPtr pScreen, int *num_ret)
RROutputPtr output = pScrPriv->outputs[o]; RROutputPtr output = pScrPriv->outputs[o];
int m, n; int m, n;
for (m = 0; m < output->numModes; m++) for (m = 0; m < output->numModes + output->numUserModes; m++)
{ {
RRModePtr mode = output->modes[m]; RRModePtr mode = (m < output->numModes ?
output->modes[m] :
output->userModes[m-output->numModes]);
for (n = 0; n < num_screen_modes; n++) for (n = 0; n < num_screen_modes; n++)
if (screen_modes[n] == mode) if (screen_modes[n] == mode)
break; break;
@ -150,6 +204,23 @@ RRModesForScreen (ScreenPtr pScreen, int *num_ret)
if (n == num_screen_modes) if (n == num_screen_modes)
screen_modes[num_screen_modes++] = mode; screen_modes[num_screen_modes++] = mode;
} }
/*
* Add all user modes for this screen
*/
for (m = 0; m < num_modes; m++)
{
RRModePtr mode = modes[m];
int n;
if (mode->userScreen != pScreen)
continue;
for (n = 0; n < num_screen_modes; n++)
if (screen_modes[n] == mode)
break;
if (n == num_screen_modes)
screen_modes[num_screen_modes++] = mode;
}
*num_ret = num_screen_modes; *num_ret = num_screen_modes;
return screen_modes; return screen_modes;
} }
@ -205,38 +276,122 @@ int
ProcRRCreateMode (ClientPtr client) ProcRRCreateMode (ClientPtr client)
{ {
REQUEST(xRRCreateModeReq); REQUEST(xRRCreateModeReq);
xRRCreateModeReply rep;
WindowPtr pWin;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
xRRModeInfo *modeInfo;
long units_after;
char *name;
int error, rc;
RRModePtr mode;
REQUEST_SIZE_MATCH(xRRCreateModeReq); REQUEST_AT_LEAST_SIZE (xRRCreateModeReq);
(void) stuff; rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
return BadImplementation; if (rc != Success)
return rc;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
modeInfo = &stuff->modeInfo;
name = (char *) (stuff + 1);
units_after = (stuff->length - (sizeof (xRRCreateModeReq) >> 2));
/* check to make sure requested name fits within the data provided */
if ((int) (modeInfo->nameLength + 3) >> 2 > units_after)
return BadLength;
mode = RRModeCreateUser (pScreen, modeInfo, name, &error);
if (!mode)
return error;
rep.type = X_Reply;
rep.pad0 = 0;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.mode = mode->mode.id;
if (client->swapped)
{
int n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.mode, n);
}
WriteToClient(client, sizeof(xRRCreateModeReply), (char *)&rep);
return client->noClientException;
} }
int int
ProcRRDestroyMode (ClientPtr client) ProcRRDestroyMode (ClientPtr client)
{ {
REQUEST(xRRDestroyModeReq); REQUEST(xRRDestroyModeReq);
RRModePtr mode;
REQUEST_SIZE_MATCH(xRRDestroyModeReq); REQUEST_SIZE_MATCH(xRRDestroyModeReq);
(void) stuff; mode = LookupIDByType (stuff->mode, RRModeType);
return BadImplementation; if (!mode)
{
client->errorValue = stuff->mode;
return RRErrorBase + BadRRMode;
}
if (!mode->userScreen)
return BadMatch;
if (mode->refcnt > 1)
return BadAccess;
FreeResource (stuff->mode, 0);
return Success;
} }
int int
ProcRRAddOutputMode (ClientPtr client) ProcRRAddOutputMode (ClientPtr client)
{ {
REQUEST(xRRAddOutputModeReq); REQUEST(xRRAddOutputModeReq);
RRModePtr mode;
RROutputPtr output;
REQUEST_SIZE_MATCH(xRRAddOutputModeReq); REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
(void) stuff; output = LookupOutput(client, stuff->output, DixReadAccess);
return BadImplementation;
if (!output)
{
client->errorValue = stuff->output;
return RRErrorBase + BadRROutput;
}
mode = LookupIDByType (stuff->mode, RRModeType);
if (!mode)
{
client->errorValue = stuff->mode;
return RRErrorBase + BadRRMode;
}
return RROutputAddUserMode (output, mode);
} }
int int
ProcRRDeleteOutputMode (ClientPtr client) ProcRRDeleteOutputMode (ClientPtr client)
{ {
REQUEST(xRRDeleteOutputModeReq); REQUEST(xRRDeleteOutputModeReq);
RRModePtr mode;
RROutputPtr output;
REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq); REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
(void) stuff; output = LookupOutput(client, stuff->output, DixReadAccess);
return BadImplementation;
if (!output)
{
client->errorValue = stuff->output;
return RRErrorBase + BadRROutput;
}
mode = LookupIDByType (stuff->mode, RRModeType);
if (!mode)
{
client->errorValue = stuff->mode;
return RRErrorBase + BadRRMode;
}
return RROutputDeleteUserMode (output, mode);
} }

View File

@ -76,6 +76,8 @@ RROutputCreate (const char *name,
output->numModes = 0; output->numModes = 0;
output->numPreferred = 0; output->numPreferred = 0;
output->modes = NULL; output->modes = NULL;
output->numUserModes = 0;
output->userModes = NULL;
output->properties = NULL; output->properties = NULL;
output->changed = FALSE; output->changed = FALSE;
output->devPrivate = devPrivate; output->devPrivate = devPrivate;
@ -192,6 +194,74 @@ RROutputSetModes (RROutputPtr output,
return TRUE; return TRUE;
} }
int
RROutputAddUserMode (RROutputPtr output,
RRModePtr mode)
{
int m;
ScreenPtr pScreen = output->pScreen;
rrScrPriv(pScreen);
RRModePtr *newModes;
/* Check to see if this mode is already listed for this output */
for (m = 0; m < output->numModes + output->numUserModes; m++)
{
RRModePtr e = (m < output->numModes ?
output->modes[m] :
output->userModes[m - output->numModes]);
if (mode == e)
return Success;
}
/* Check with the DDX to see if this mode is OK */
if (pScrPriv->rrOutputValidateMode)
if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode))
return BadMatch;
if (output->userModes)
newModes = xrealloc (output->userModes,
(output->numUserModes + 1) * sizeof (RRModePtr));
else
newModes = xalloc (sizeof (RRModePtr));
if (!newModes)
return BadAlloc;
output->userModes = newModes;
output->userModes[output->numUserModes++] = mode;
++mode->refcnt;
RROutputChanged (output, TRUE);
RRTellChanged (pScreen);
return Success;
}
int
RROutputDeleteUserMode (RROutputPtr output,
RRModePtr mode)
{
int m;
/* Find this mode in the user mode list */
for (m = 0; m < output->numUserModes; m++)
{
RRModePtr e = output->userModes[m];
if (mode == e)
break;
}
/* Not there, access error */
if (m == output->numUserModes)
return BadAccess;
/* make sure the mode isn't active for this output */
if (output->crtc && output->crtc->mode == mode)
return BadMatch;
memmove (output->userModes + m, output->userModes + m + 1,
(output->numUserModes - m - 1) * sizeof (RRModePtr));
RRModeDestroy (mode);
return Success;
}
Bool Bool
RROutputSetCrtcs (RROutputPtr output, RROutputSetCrtcs (RROutputPtr output,
RRCrtcPtr *crtcs, RRCrtcPtr *crtcs,
@ -308,9 +378,9 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
* Destroy a Output at shutdown * Destroy a Output at shutdown
*/ */
void void
RROutputDestroy (RROutputPtr crtc) RROutputDestroy (RROutputPtr output)
{ {
FreeResource (crtc->id, 0); FreeResource (output->id, 0);
} }
static int static int
@ -318,6 +388,7 @@ RROutputDestroyResource (pointer value, XID pid)
{ {
RROutputPtr output = (RROutputPtr) value; RROutputPtr output = (RROutputPtr) value;
ScreenPtr pScreen = output->pScreen; ScreenPtr pScreen = output->pScreen;
int m;
if (pScreen) if (pScreen)
{ {
@ -335,8 +406,15 @@ RROutputDestroyResource (pointer value, XID pid)
} }
} }
} }
/* XXX destroy all modes? */
if (output->modes) if (output->modes)
xfree (output->modes); xfree (output->modes);
for (m = 0; m < output->numUserModes; m++)
RRModeDestroy (output->userModes[m]);
if (output->userModes)
xfree (output->userModes);
if (output->crtcs) if (output->crtcs)
xfree (output->crtcs); xfree (output->crtcs);
if (output->clones) if (output->clones)
@ -383,7 +461,10 @@ ProcRRGetOutputInfo (ClientPtr client)
output = LookupOutput(client, stuff->output, DixReadAccess); output = LookupOutput(client, stuff->output, DixReadAccess);
if (!output) if (!output)
{
client->errorValue = stuff->output;
return RRErrorBase + BadRROutput; return RRErrorBase + BadRROutput;
}
pScreen = output->pScreen; pScreen = output->pScreen;
pScrPriv = rrGetScrPriv(pScreen); pScrPriv = rrGetScrPriv(pScreen);
@ -398,13 +479,13 @@ ProcRRGetOutputInfo (ClientPtr client)
rep.connection = output->connection; rep.connection = output->connection;
rep.subpixelOrder = output->subpixelOrder; rep.subpixelOrder = output->subpixelOrder;
rep.nCrtcs = output->numCrtcs; rep.nCrtcs = output->numCrtcs;
rep.nModes = output->numModes; rep.nModes = output->numModes + output->numUserModes;
rep.nPreferred = output->numPreferred; rep.nPreferred = output->numPreferred;
rep.nClones = output->numClones; rep.nClones = output->numClones;
rep.nameLength = output->nameLength; rep.nameLength = output->nameLength;
extraLen = ((output->numCrtcs + extraLen = ((output->numCrtcs +
output->numModes + output->numModes + output->numUserModes +
output->numClones + output->numClones +
((rep.nameLength + 3) >> 2)) << 2); ((rep.nameLength + 3) >> 2)) << 2);
@ -420,7 +501,7 @@ ProcRRGetOutputInfo (ClientPtr client)
crtcs = (RRCrtc *) extra; crtcs = (RRCrtc *) extra;
modes = (RRMode *) (crtcs + output->numCrtcs); modes = (RRMode *) (crtcs + output->numCrtcs);
clones = (RROutput *) (modes + output->numModes); clones = (RROutput *) (modes + output->numModes + output->numUserModes);
name = (char *) (clones + output->numClones); name = (char *) (clones + output->numClones);
for (i = 0; i < output->numCrtcs; i++) for (i = 0; i < output->numCrtcs; i++)
@ -429,9 +510,12 @@ ProcRRGetOutputInfo (ClientPtr client)
if (client->swapped) if (client->swapped)
swapl (&crtcs[i], n); swapl (&crtcs[i], n);
} }
for (i = 0; i < output->numModes; i++) for (i = 0; i < output->numModes + output->numUserModes; i++)
{ {
modes[i] = output->modes[i]->mode.id; if (i < output->numModes)
modes[i] = output->modes[i]->mode.id;
else
modes[i] = output->userModes[i - output->numModes]->mode.id;
if (client->swapped) if (client->swapped)
swapl (&modes[i], n); swapl (&modes[i], n);
} }

View File

@ -473,7 +473,7 @@ RR10GetData (ScreenPtr pScreen, RROutputPtr output)
{ {
RR10DataPtr data; RR10DataPtr data;
RRScreenSizePtr size; RRScreenSizePtr size;
int nmode = output->numModes; int nmode = output->numModes + output->numUserModes;
int o, os, l, r; int o, os, l, r;
RRScreenRatePtr refresh; RRScreenRatePtr refresh;
CARD16 vRefresh; CARD16 vRefresh;
@ -500,11 +500,14 @@ RR10GetData (ScreenPtr pScreen, RROutputPtr output)
/* /*
* find modes not yet listed * find modes not yet listed
*/ */
for (o = 0; o < output->numModes; o++) for (o = 0; o < output->numModes + output->numUserModes; o++)
{ {
if (used[o]) continue; if (used[o]) continue;
mode = output->modes[o]; if (o < output->numModes)
mode = output->modes[o];
else
mode = output->userModes[o - output->numModes];
l = data->nsize; l = data->nsize;
size[l].id = data->nsize; size[l].id = data->nsize;
@ -524,9 +527,12 @@ RR10GetData (ScreenPtr pScreen, RROutputPtr output)
/* /*
* Find all modes with matching size * Find all modes with matching size
*/ */
for (os = o; os < output->numModes; os++) for (os = o; os < output->numModes + output->numUserModes; os++)
{ {
mode = output->modes[os]; if (os < output->numModes)
mode = output->modes[os];
else
mode = output->userModes[os - output->numModes];
if (mode->mode.width == size[l].width && if (mode->mode.width == size[l].width &&
mode->mode.height == size[l].height) mode->mode.height == size[l].height)
{ {