diff options
author | Keith Packard <keithp@guitar.keithp.com> | 2007-02-18 23:49:38 -0800 |
---|---|---|
committer | Keith Packard <keithp@neko.keithp.com> | 2007-03-17 23:20:07 -0700 |
commit | 2c93083edd29a65e73bb2e8eff9d353e92845c9b (patch) | |
tree | 596e34a8f006c18bf9984e87303dac546a048e5c /randr/rroutput.c | |
parent | 3bffb281260476d2f74f0bf451d85d2f7cacd6c4 (diff) |
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.
Diffstat (limited to 'randr/rroutput.c')
-rw-r--r-- | randr/rroutput.c | 98 |
1 files changed, 91 insertions, 7 deletions
diff --git a/randr/rroutput.c b/randr/rroutput.c index df1741f5c..6e95c9598 100644 --- a/randr/rroutput.c +++ b/randr/rroutput.c @@ -76,6 +76,8 @@ RROutputCreate (const char *name, output->numModes = 0; output->numPreferred = 0; output->modes = NULL; + output->numUserModes = 0; + output->userModes = NULL; output->properties = NULL; output->changed = FALSE; output->devPrivate = devPrivate; @@ -192,6 +194,74 @@ RROutputSetModes (RROutputPtr output, 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 RROutputSetCrtcs (RROutputPtr output, RRCrtcPtr *crtcs, @@ -308,9 +378,9 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) * Destroy a Output at shutdown */ void -RROutputDestroy (RROutputPtr crtc) +RROutputDestroy (RROutputPtr output) { - FreeResource (crtc->id, 0); + FreeResource (output->id, 0); } static int @@ -318,6 +388,7 @@ RROutputDestroyResource (pointer value, XID pid) { RROutputPtr output = (RROutputPtr) value; ScreenPtr pScreen = output->pScreen; + int m; if (pScreen) { @@ -335,8 +406,15 @@ RROutputDestroyResource (pointer value, XID pid) } } } + /* XXX destroy all modes? */ if (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) xfree (output->crtcs); if (output->clones) @@ -383,7 +461,10 @@ ProcRRGetOutputInfo (ClientPtr client) output = LookupOutput(client, stuff->output, DixReadAccess); if (!output) + { + client->errorValue = stuff->output; return RRErrorBase + BadRROutput; + } pScreen = output->pScreen; pScrPriv = rrGetScrPriv(pScreen); @@ -398,13 +479,13 @@ ProcRRGetOutputInfo (ClientPtr client) rep.connection = output->connection; rep.subpixelOrder = output->subpixelOrder; rep.nCrtcs = output->numCrtcs; - rep.nModes = output->numModes; + rep.nModes = output->numModes + output->numUserModes; rep.nPreferred = output->numPreferred; rep.nClones = output->numClones; rep.nameLength = output->nameLength; extraLen = ((output->numCrtcs + - output->numModes + + output->numModes + output->numUserModes + output->numClones + ((rep.nameLength + 3) >> 2)) << 2); @@ -420,7 +501,7 @@ ProcRRGetOutputInfo (ClientPtr client) crtcs = (RRCrtc *) extra; modes = (RRMode *) (crtcs + output->numCrtcs); - clones = (RROutput *) (modes + output->numModes); + clones = (RROutput *) (modes + output->numModes + output->numUserModes); name = (char *) (clones + output->numClones); for (i = 0; i < output->numCrtcs; i++) @@ -429,9 +510,12 @@ ProcRRGetOutputInfo (ClientPtr client) if (client->swapped) 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) swapl (&modes[i], n); } |