summaryrefslogtreecommitdiff
path: root/randr
diff options
context:
space:
mode:
authorKeith Packard <keithp@guitar.keithp.com>2007-02-18 23:49:38 -0800
committerKeith Packard <keithp@guitar.keithp.com>2007-02-18 23:49:38 -0800
commit63cc2a51ef87130c632a874672a8c9167f14314e (patch)
treebb91c2f462bcb61d9d9ad86452009e34c1590749 /randr
parent1418fd8ce4c8459775bb362ca5fed4cacf1489bf (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.
Diffstat (limited to 'randr')
-rw-r--r--randr/mirandr.c17
-rw-r--r--randr/randrstr.h34
-rw-r--r--randr/rrcrtc.c11
-rw-r--r--randr/rrinfo.c6
-rw-r--r--randr/rrmode.c218
-rw-r--r--randr/rroutput.c98
-rw-r--r--randr/rrscreen.c16
7 files changed, 350 insertions, 50 deletions
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 0b763e111..47136fb96 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -73,6 +73,20 @@ miRROutputSetProperty (ScreenPtr pScreen,
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
* displayed at a time, but that all visuals of that depth
@@ -102,7 +116,8 @@ miRandRInit (ScreenPtr pScreen)
pScrPriv->rrCrtcSet = miRRCrtcSet;
pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma;
pScrPriv->rrOutputSetProperty = miRROutputSetProperty;
-
+ pScrPriv->rrOutputValidateMode = miRROutputValidateMode;
+ pScrPriv->rrModeDestroy = miRRModeDestroy;
RRScreenSetSizeRange (pScreen,
pScreen->width, pScreen->height,
diff --git a/randr/randrstr.h b/randr/randrstr.h
index f86f9b5d0..1fc2520be 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -80,7 +80,7 @@ struct _rrMode {
xRRModeInfo mode;
char *name;
void *devPrivate;
- Bool userDefined;
+ ScreenPtr userScreen;
};
struct _rrPropertyValue {
@@ -135,6 +135,8 @@ struct _rrOutput {
int numModes;
int numPreferred;
RRModePtr *modes;
+ int numUserModes;
+ RRModePtr *userModes;
Bool changed;
RRPropertyPtr properties;
void *devPrivate;
@@ -164,6 +166,13 @@ typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen,
Atom property,
RRPropertyValuePtr value);
+typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen,
+ RROutputPtr output,
+ RRModePtr mode);
+
+typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen,
+ RRModePtr mode);
+
#endif
typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
@@ -208,6 +217,8 @@ typedef struct _rrScrPriv {
RRCrtcSetProcPtr rrCrtcSet;
RRCrtcSetGammaProcPtr rrCrtcSetGamma;
RROutputSetPropertyProcPtr rrOutputSetProperty;
+ RROutputValidateModeProcPtr rrOutputValidateMode;
+ RRModeDestroyProcPtr rrModeDestroy;
#endif
/*
@@ -394,6 +405,15 @@ miRROutputSetProperty (ScreenPtr pScreen,
Atom property,
RRPropertyValuePtr value);
+Bool
+miRROutputValidateMode (ScreenPtr pScreen,
+ RROutputPtr output,
+ RRModePtr mode);
+
+void
+miRRModeDestroy (ScreenPtr pScreen,
+ RRModePtr mode);
+
/* randr.c */
/*
* Send all pending events
@@ -548,6 +568,10 @@ Bool
RRCrtcGammaSetSize (RRCrtcPtr crtc,
int size);
+/*
+ * Return the area of the frame buffer scanned out by the crtc,
+ * taking into account the current mode and rotation
+ */
void
RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
@@ -671,6 +695,14 @@ RROutputSetModes (RROutputPtr output,
int numModes,
int numPreferred);
+int
+RROutputAddUserMode (RROutputPtr output,
+ RRModePtr mode);
+
+int
+RROutputDeleteUserMode (RROutputPtr output,
+ RRModePtr mode);
+
Bool
RROutputSetCrtcs (RROutputPtr output,
RRCrtcPtr *crtcs,
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 2ae9040d1..a90b07289 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -655,10 +655,15 @@ ProcRRSetCrtcConfig (ClientPtr client)
return BadMatch;
}
/* validate mode for this output */
- for (j = 0; j < outputs[i]->numModes; j++)
- if (outputs[i]->modes[j] == mode)
+ for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
+ {
+ RRModePtr m = (j < outputs[i]->numModes ?
+ outputs[i]->modes[j] :
+ outputs[i]->userModes[j - outputs[i]->numModes]);
+ if (m == mode)
break;
- if (j == outputs[i]->numModes)
+ }
+ if (j == outputs[i]->numModes + outputs[i]->numUserModes)
{
if (outputs)
xfree (outputs);
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 797cdb1b4..549d501dc 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -157,9 +157,11 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
pScrPriv->nSizes = 0;
/* 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 height = mode->mode.height;
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 261e1b75f..e268cc2f3 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,123 @@ int
ProcRRCreateMode (ClientPtr client)
{
REQUEST(xRRCreateModeReq);
+ xRRCreateModeReply rep;
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ xRRModeInfo *modeInfo;
+ long units_after;
+ char *name;
+ int error;
+ RRModePtr mode;
+
+ REQUEST_AT_LEAST_SIZE (xRRCreateModeReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ SecurityReadAccess);
+
+ if (!pWin)
+ return BadWindow;
+ 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, SecurityReadAccess);
+
+ 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, SecurityReadAccess);
+
+ 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);
}
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 8007a8a55..31ec92421 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, SecurityReadAccess);
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);
}
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 7a33ef674..8aa26fa90 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -479,7 +479,7 @@ RR10GetData (ScreenPtr pScreen, RROutputPtr output)
{
RR10DataPtr data;
RRScreenSizePtr size;
- int nmode = output->numModes;
+ int nmode = output->numModes + output->numUserModes;
int o, os, l, r;
RRScreenRatePtr refresh;
CARD16 vRefresh;
@@ -506,11 +506,14 @@ RR10GetData (ScreenPtr pScreen, RROutputPtr output)
/*
* 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;
- mode = output->modes[o];
+ if (o < output->numModes)
+ mode = output->modes[o];
+ else
+ mode = output->userModes[o - output->numModes];
l = data->nsize;
size[l].id = data->nsize;
@@ -530,9 +533,12 @@ RR10GetData (ScreenPtr pScreen, RROutputPtr output)
/*
* 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 &&
mode->mode.height == size[l].height)
{