summaryrefslogtreecommitdiff
path: root/randr/rroutput.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@guitar.keithp.com>2007-02-18 23:49:38 -0800
committerKeith Packard <keithp@neko.keithp.com>2007-03-17 23:20:07 -0700
commit2c93083edd29a65e73bb2e8eff9d353e92845c9b (patch)
tree596e34a8f006c18bf9984e87303dac546a048e5c /randr/rroutput.c
parent3bffb281260476d2f74f0bf451d85d2f7cacd6c4 (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.c98
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);
}