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/rrmode.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/rrmode.c')
-rw-r--r-- | randr/rrmode.c | 217 |
1 files changed, 186 insertions, 31 deletions
diff --git a/randr/rrmode.c b/randr/rrmode.c index 261e1b75f..11175810c 100644 --- a/randr/rrmode.c +++ b/randr/rrmode.c @@ -48,25 +48,13 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo *b) static int num_modes; static RRModePtr *modes; -RRModePtr -RRModeGet (xRRModeInfo *modeInfo, - const char *name) +static RRModePtr +RRModeCreate (xRRModeInfo *modeInfo, + const char *name, + ScreenPtr userScreen) { - int i; - 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; - } - } - + RRModePtr mode, *newModes; + if (!RRInit ()) return NULL; @@ -78,7 +66,7 @@ RRModeGet (xRRModeInfo *modeInfo, mode->name = (char *) (mode + 1); memcpy (mode->name, name, modeInfo->nameLength); mode->name[modeInfo->nameLength] = '\0'; - mode->userDefined = FALSE; + mode->userScreen = userScreen; if (num_modes) newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr)); @@ -104,11 +92,75 @@ RRModeGet (xRRModeInfo *modeInfo, 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 * RRModesForScreen (ScreenPtr pScreen, int *num_ret) { rrScrPriv(pScreen); - int o, c; + int o, c, m; RRModePtr *screen_modes; int num_screen_modes = 0; @@ -122,9 +174,11 @@ RRModesForScreen (ScreenPtr pScreen, int *num_ret) RROutputPtr output = pScrPriv->outputs[o]; 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++) if (screen_modes[n] == mode) break; @@ -150,6 +204,23 @@ RRModesForScreen (ScreenPtr pScreen, int *num_ret) if (n == num_screen_modes) 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; return screen_modes; } @@ -205,38 +276,122 @@ int ProcRRCreateMode (ClientPtr client) { REQUEST(xRRCreateModeReq); + xRRCreateModeReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + xRRModeInfo *modeInfo; + long units_after; + char *name; + int error, rc; + RRModePtr mode; + + REQUEST_AT_LEAST_SIZE (xRRCreateModeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); - REQUEST_SIZE_MATCH(xRRCreateModeReq); - (void) stuff; - return BadImplementation; + 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 ProcRRDestroyMode (ClientPtr client) { REQUEST(xRRDestroyModeReq); + RRModePtr mode; REQUEST_SIZE_MATCH(xRRDestroyModeReq); - (void) stuff; - return BadImplementation; + mode = LookupIDByType (stuff->mode, RRModeType); + 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 ProcRRAddOutputMode (ClientPtr client) { REQUEST(xRRAddOutputModeReq); + RRModePtr mode; + RROutputPtr output; REQUEST_SIZE_MATCH(xRRAddOutputModeReq); - (void) stuff; - return BadImplementation; + output = LookupOutput(client, stuff->output, DixReadAccess); + + 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 ProcRRDeleteOutputMode (ClientPtr client) { REQUEST(xRRDeleteOutputModeReq); + RRModePtr mode; + RROutputPtr output; REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq); - (void) stuff; - return BadImplementation; + output = LookupOutput(client, stuff->output, DixReadAccess); + + 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); } |