rrscreen.c revision 05b261ec
105b261ecSmrg/*
205b261ecSmrg * Copyright © 2006 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that copyright
705b261ecSmrg * notice and this permission notice appear in supporting documentation, and
805b261ecSmrg * that the name of the copyright holders not be used in advertising or
905b261ecSmrg * publicity pertaining to distribution of the software without specific,
1005b261ecSmrg * written prior permission.  The copyright holders make no representations
1105b261ecSmrg * about the suitability of this software for any purpose.  It is provided "as
1205b261ecSmrg * is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2005b261ecSmrg * OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
2305b261ecSmrg#include "randrstr.h"
2405b261ecSmrg
2505b261ecSmrgextern char	*ConnectionInfo;
2605b261ecSmrg
2705b261ecSmrgstatic int padlength[4] = {0, 3, 2, 1};
2805b261ecSmrg
2905b261ecSmrgstatic CARD16
3005b261ecSmrgRR10CurrentSizeID (ScreenPtr pScreen);
3105b261ecSmrg
3205b261ecSmrg/*
3305b261ecSmrg * Edit connection information block so that new clients
3405b261ecSmrg * see the current screen size on connect
3505b261ecSmrg */
3605b261ecSmrgstatic void
3705b261ecSmrgRREditConnectionInfo (ScreenPtr pScreen)
3805b261ecSmrg{
3905b261ecSmrg    xConnSetup	    *connSetup;
4005b261ecSmrg    char	    *vendor;
4105b261ecSmrg    xPixmapFormat   *formats;
4205b261ecSmrg    xWindowRoot	    *root;
4305b261ecSmrg    xDepth	    *depth;
4405b261ecSmrg    xVisualType	    *visual;
4505b261ecSmrg    int		    screen = 0;
4605b261ecSmrg    int		    d;
4705b261ecSmrg
4805b261ecSmrg    connSetup = (xConnSetup *) ConnectionInfo;
4905b261ecSmrg    vendor = (char *) connSetup + sizeof (xConnSetup);
5005b261ecSmrg    formats = (xPixmapFormat *) ((char *) vendor +
5105b261ecSmrg				 connSetup->nbytesVendor +
5205b261ecSmrg				 padlength[connSetup->nbytesVendor & 3]);
5305b261ecSmrg    root = (xWindowRoot *) ((char *) formats +
5405b261ecSmrg			    sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
5505b261ecSmrg    while (screen != pScreen->myNum)
5605b261ecSmrg    {
5705b261ecSmrg	depth = (xDepth *) ((char *) root +
5805b261ecSmrg			    sizeof (xWindowRoot));
5905b261ecSmrg	for (d = 0; d < root->nDepths; d++)
6005b261ecSmrg	{
6105b261ecSmrg	    visual = (xVisualType *) ((char *) depth +
6205b261ecSmrg				      sizeof (xDepth));
6305b261ecSmrg	    depth = (xDepth *) ((char *) visual +
6405b261ecSmrg				depth->nVisuals * sizeof (xVisualType));
6505b261ecSmrg	}
6605b261ecSmrg	root = (xWindowRoot *) ((char *) depth);
6705b261ecSmrg	screen++;
6805b261ecSmrg    }
6905b261ecSmrg    root->pixWidth = pScreen->width;
7005b261ecSmrg    root->pixHeight = pScreen->height;
7105b261ecSmrg    root->mmWidth = pScreen->mmWidth;
7205b261ecSmrg    root->mmHeight = pScreen->mmHeight;
7305b261ecSmrg}
7405b261ecSmrg
7505b261ecSmrgvoid
7605b261ecSmrgRRSendConfigNotify (ScreenPtr pScreen)
7705b261ecSmrg{
7805b261ecSmrg    WindowPtr	pWin = WindowTable[pScreen->myNum];
7905b261ecSmrg    xEvent	event;
8005b261ecSmrg
8105b261ecSmrg    event.u.u.type = ConfigureNotify;
8205b261ecSmrg    event.u.configureNotify.window = pWin->drawable.id;
8305b261ecSmrg    event.u.configureNotify.aboveSibling = None;
8405b261ecSmrg    event.u.configureNotify.x = 0;
8505b261ecSmrg    event.u.configureNotify.y = 0;
8605b261ecSmrg
8705b261ecSmrg    /* XXX xinerama stuff ? */
8805b261ecSmrg
8905b261ecSmrg    event.u.configureNotify.width = pWin->drawable.width;
9005b261ecSmrg    event.u.configureNotify.height = pWin->drawable.height;
9105b261ecSmrg    event.u.configureNotify.borderWidth = wBorderWidth (pWin);
9205b261ecSmrg    event.u.configureNotify.override = pWin->overrideRedirect;
9305b261ecSmrg    DeliverEvents(pWin, &event, 1, NullWindow);
9405b261ecSmrg}
9505b261ecSmrg
9605b261ecSmrgvoid
9705b261ecSmrgRRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
9805b261ecSmrg{
9905b261ecSmrg    rrScrPriv (pScreen);
10005b261ecSmrg    xRRScreenChangeNotifyEvent	se;
10105b261ecSmrg    RRCrtcPtr	crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
10205b261ecSmrg    WindowPtr	pRoot = WindowTable[pScreen->myNum];
10305b261ecSmrg
10405b261ecSmrg    se.type = RRScreenChangeNotify + RREventBase;
10505b261ecSmrg    se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
10605b261ecSmrg    se.timestamp = pScrPriv->lastSetTime.milliseconds;
10705b261ecSmrg    se.sequenceNumber = client->sequence;
10805b261ecSmrg    se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
10905b261ecSmrg    se.root =  pRoot->drawable.id;
11005b261ecSmrg    se.window = pWin->drawable.id;
11105b261ecSmrg#ifdef RENDER
11205b261ecSmrg    se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
11305b261ecSmrg#else
11405b261ecSmrg    se.subpixelOrder = SubPixelUnknown;
11505b261ecSmrg#endif
11605b261ecSmrg
11705b261ecSmrg    se.sequenceNumber = client->sequence;
11805b261ecSmrg    se.sizeID = RR10CurrentSizeID (pScreen);
11905b261ecSmrg
12005b261ecSmrg    if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) {
12105b261ecSmrg	se.widthInPixels = pScreen->height;
12205b261ecSmrg	se.heightInPixels = pScreen->width;
12305b261ecSmrg	se.widthInMillimeters = pScreen->mmHeight;
12405b261ecSmrg	se.heightInMillimeters = pScreen->mmWidth;
12505b261ecSmrg    } else {
12605b261ecSmrg	se.widthInPixels = pScreen->width;
12705b261ecSmrg	se.heightInPixels = pScreen->height;
12805b261ecSmrg	se.widthInMillimeters = pScreen->mmWidth;
12905b261ecSmrg	se.heightInMillimeters = pScreen->mmHeight;
13005b261ecSmrg    }
13105b261ecSmrg
13205b261ecSmrg    WriteEventsToClient (client, 1, (xEvent *) &se);
13305b261ecSmrg}
13405b261ecSmrg
13505b261ecSmrg/*
13605b261ecSmrg * Notify the extension that the screen size has been changed.
13705b261ecSmrg * The driver is responsible for calling this whenever it has changed
13805b261ecSmrg * the size of the screen
13905b261ecSmrg */
14005b261ecSmrgvoid
14105b261ecSmrgRRScreenSizeNotify (ScreenPtr	pScreen)
14205b261ecSmrg{
14305b261ecSmrg    rrScrPriv(pScreen);
14405b261ecSmrg    /*
14505b261ecSmrg     * Deliver ConfigureNotify events when root changes
14605b261ecSmrg     * pixel size
14705b261ecSmrg     */
14805b261ecSmrg    if (pScrPriv->width == pScreen->width &&
14905b261ecSmrg	pScrPriv->height == pScreen->height &&
15005b261ecSmrg	pScrPriv->mmWidth == pScreen->mmWidth &&
15105b261ecSmrg	pScrPriv->mmHeight == pScreen->mmHeight)
15205b261ecSmrg	return;
15305b261ecSmrg
15405b261ecSmrg    pScrPriv->width = pScreen->width;
15505b261ecSmrg    pScrPriv->height = pScreen->height;
15605b261ecSmrg    pScrPriv->mmWidth = pScreen->mmWidth;
15705b261ecSmrg    pScrPriv->mmHeight = pScreen->mmHeight;
15805b261ecSmrg    pScrPriv->changed = TRUE;
15905b261ecSmrg/*    pScrPriv->sizeChanged = TRUE; */
16005b261ecSmrg
16105b261ecSmrg    RRTellChanged (pScreen);
16205b261ecSmrg    RRSendConfigNotify (pScreen);
16305b261ecSmrg    RREditConnectionInfo (pScreen);
16405b261ecSmrg
16505b261ecSmrg    RRPointerScreenConfigured (pScreen);
16605b261ecSmrg    /*
16705b261ecSmrg     * Fix pointer bounds and location
16805b261ecSmrg     */
16905b261ecSmrg    ScreenRestructured (pScreen);
17005b261ecSmrg}
17105b261ecSmrg
17205b261ecSmrg/*
17305b261ecSmrg * Request that the screen be resized
17405b261ecSmrg */
17505b261ecSmrgBool
17605b261ecSmrgRRScreenSizeSet (ScreenPtr  pScreen,
17705b261ecSmrg		 CARD16	    width,
17805b261ecSmrg		 CARD16	    height,
17905b261ecSmrg		 CARD32	    mmWidth,
18005b261ecSmrg		 CARD32	    mmHeight)
18105b261ecSmrg{
18205b261ecSmrg    rrScrPriv(pScreen);
18305b261ecSmrg
18405b261ecSmrg#if RANDR_12_INTERFACE
18505b261ecSmrg    if (pScrPriv->rrScreenSetSize)
18605b261ecSmrg    {
18705b261ecSmrg	return (*pScrPriv->rrScreenSetSize) (pScreen,
18805b261ecSmrg					     width, height,
18905b261ecSmrg					     mmWidth, mmHeight);
19005b261ecSmrg    }
19105b261ecSmrg#endif
19205b261ecSmrg#if RANDR_10_INTERFACE
19305b261ecSmrg    if (pScrPriv->rrSetConfig)
19405b261ecSmrg    {
19505b261ecSmrg	return TRUE;	/* can't set size separately */
19605b261ecSmrg    }
19705b261ecSmrg#endif
19805b261ecSmrg    return FALSE;
19905b261ecSmrg}
20005b261ecSmrg
20105b261ecSmrg/*
20205b261ecSmrg * Retrieve valid screen size range
20305b261ecSmrg */
20405b261ecSmrgint
20505b261ecSmrgProcRRGetScreenSizeRange (ClientPtr client)
20605b261ecSmrg{
20705b261ecSmrg    REQUEST(xRRGetScreenSizeRangeReq);
20805b261ecSmrg    xRRGetScreenSizeRangeReply	rep;
20905b261ecSmrg    WindowPtr			pWin;
21005b261ecSmrg    ScreenPtr			pScreen;
21105b261ecSmrg    rrScrPrivPtr		pScrPriv;
21205b261ecSmrg    int				rc;
21305b261ecSmrg
21405b261ecSmrg    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
21505b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
21605b261ecSmrg    if (rc != Success)
21705b261ecSmrg	return rc;
21805b261ecSmrg
21905b261ecSmrg    pScreen = pWin->drawable.pScreen;
22005b261ecSmrg    pScrPriv = rrGetScrPriv(pScreen);
22105b261ecSmrg
22205b261ecSmrg    rep.type = X_Reply;
22305b261ecSmrg    rep.pad = 0;
22405b261ecSmrg    rep.sequenceNumber = client->sequence;
22505b261ecSmrg    rep.length = 0;
22605b261ecSmrg
22705b261ecSmrg    if (pScrPriv)
22805b261ecSmrg    {
22905b261ecSmrg	if (!RRGetInfo (pScreen))
23005b261ecSmrg	    return BadAlloc;
23105b261ecSmrg	rep.minWidth  = pScrPriv->minWidth;
23205b261ecSmrg	rep.minHeight = pScrPriv->minHeight;
23305b261ecSmrg	rep.maxWidth  = pScrPriv->maxWidth;
23405b261ecSmrg	rep.maxHeight = pScrPriv->maxHeight;
23505b261ecSmrg    }
23605b261ecSmrg    else
23705b261ecSmrg    {
23805b261ecSmrg	rep.maxWidth  = rep.minWidth  = pScreen->width;
23905b261ecSmrg	rep.maxHeight = rep.minHeight = pScreen->height;
24005b261ecSmrg    }
24105b261ecSmrg    if (client->swapped)
24205b261ecSmrg    {
24305b261ecSmrg	int n;
24405b261ecSmrg
24505b261ecSmrg    	swaps(&rep.sequenceNumber, n);
24605b261ecSmrg    	swapl(&rep.length, n);
24705b261ecSmrg	swaps(&rep.minWidth, n);
24805b261ecSmrg	swaps(&rep.minHeight, n);
24905b261ecSmrg	swaps(&rep.maxWidth, n);
25005b261ecSmrg	swaps(&rep.maxHeight, n);
25105b261ecSmrg    }
25205b261ecSmrg    WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep);
25305b261ecSmrg    return (client->noClientException);
25405b261ecSmrg}
25505b261ecSmrg
25605b261ecSmrgint
25705b261ecSmrgProcRRSetScreenSize (ClientPtr client)
25805b261ecSmrg{
25905b261ecSmrg    REQUEST(xRRSetScreenSizeReq);
26005b261ecSmrg    WindowPtr		pWin;
26105b261ecSmrg    ScreenPtr		pScreen;
26205b261ecSmrg    rrScrPrivPtr	pScrPriv;
26305b261ecSmrg    int			i, rc;
26405b261ecSmrg
26505b261ecSmrg    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
26605b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
26705b261ecSmrg    if (rc != Success)
26805b261ecSmrg	return rc;
26905b261ecSmrg
27005b261ecSmrg    pScreen = pWin->drawable.pScreen;
27105b261ecSmrg    pScrPriv = rrGetScrPriv(pScreen);
27205b261ecSmrg    if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width)
27305b261ecSmrg    {
27405b261ecSmrg	client->errorValue = stuff->width;
27505b261ecSmrg	return BadValue;
27605b261ecSmrg    }
27705b261ecSmrg    if (stuff->height < pScrPriv->minHeight ||
27805b261ecSmrg	pScrPriv->maxHeight < stuff->height)
27905b261ecSmrg    {
28005b261ecSmrg	client->errorValue = stuff->height;
28105b261ecSmrg	return BadValue;
28205b261ecSmrg    }
28305b261ecSmrg    for (i = 0; i < pScrPriv->numCrtcs; i++)
28405b261ecSmrg    {
28505b261ecSmrg	RRCrtcPtr   crtc = pScrPriv->crtcs[i];
28605b261ecSmrg	RRModePtr   mode = crtc->mode;
28705b261ecSmrg	if (mode)
28805b261ecSmrg	{
28905b261ecSmrg	    int		source_width = mode->mode.width;
29005b261ecSmrg	    int		source_height = mode->mode.height;
29105b261ecSmrg	    Rotation	rotation = crtc->rotation;
29205b261ecSmrg
29305b261ecSmrg	    if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270)
29405b261ecSmrg	    {
29505b261ecSmrg		source_width = mode->mode.height;
29605b261ecSmrg		source_height = mode->mode.width;
29705b261ecSmrg	    }
29805b261ecSmrg
29905b261ecSmrg	    if (crtc->x + source_width > stuff->width ||
30005b261ecSmrg		crtc->y + source_height > stuff->height)
30105b261ecSmrg	    return BadMatch;
30205b261ecSmrg	}
30305b261ecSmrg    }
30405b261ecSmrg    if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0)
30505b261ecSmrg    {
30605b261ecSmrg	client->errorValue = 0;
30705b261ecSmrg	return BadValue;
30805b261ecSmrg    }
30905b261ecSmrg    if (!RRScreenSizeSet (pScreen,
31005b261ecSmrg			  stuff->width, stuff->height,
31105b261ecSmrg			  stuff->widthInMillimeters,
31205b261ecSmrg			  stuff->heightInMillimeters))
31305b261ecSmrg    {
31405b261ecSmrg	return BadMatch;
31505b261ecSmrg    }
31605b261ecSmrg    return Success;
31705b261ecSmrg}
31805b261ecSmrg
31905b261ecSmrgint
32005b261ecSmrgProcRRGetScreenResources (ClientPtr client)
32105b261ecSmrg{
32205b261ecSmrg    REQUEST(xRRGetScreenResourcesReq);
32305b261ecSmrg    xRRGetScreenResourcesReply  rep;
32405b261ecSmrg    WindowPtr			pWin;
32505b261ecSmrg    ScreenPtr			pScreen;
32605b261ecSmrg    rrScrPrivPtr		pScrPriv;
32705b261ecSmrg    CARD8			*extra;
32805b261ecSmrg    unsigned long		extraLen;
32905b261ecSmrg    int				i, n, rc;
33005b261ecSmrg    RRCrtc			*crtcs;
33105b261ecSmrg    RROutput			*outputs;
33205b261ecSmrg    xRRModeInfo			*modeinfos;
33305b261ecSmrg    CARD8			*names;
33405b261ecSmrg
33505b261ecSmrg    REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
33605b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
33705b261ecSmrg    if (rc != Success)
33805b261ecSmrg	return rc;
33905b261ecSmrg
34005b261ecSmrg    pScreen = pWin->drawable.pScreen;
34105b261ecSmrg    pScrPriv = rrGetScrPriv(pScreen);
34205b261ecSmrg    rep.pad = 0;
34305b261ecSmrg
34405b261ecSmrg    if (pScrPriv)
34505b261ecSmrg	if (!RRGetInfo (pScreen))
34605b261ecSmrg	    return BadAlloc;
34705b261ecSmrg
34805b261ecSmrg    if (!pScrPriv)
34905b261ecSmrg    {
35005b261ecSmrg	rep.type = X_Reply;
35105b261ecSmrg	rep.sequenceNumber = client->sequence;
35205b261ecSmrg	rep.length = 0;
35305b261ecSmrg	rep.timestamp = currentTime.milliseconds;
35405b261ecSmrg	rep.configTimestamp = currentTime.milliseconds;
35505b261ecSmrg	rep.nCrtcs = 0;
35605b261ecSmrg	rep.nOutputs = 0;
35705b261ecSmrg	rep.nModes = 0;
35805b261ecSmrg	rep.nbytesNames = 0;
35905b261ecSmrg	extra = NULL;
36005b261ecSmrg	extraLen = 0;
36105b261ecSmrg    }
36205b261ecSmrg    else
36305b261ecSmrg    {
36405b261ecSmrg	RRModePtr   *modes;
36505b261ecSmrg	int	    num_modes;
36605b261ecSmrg
36705b261ecSmrg	modes = RRModesForScreen (pScreen, &num_modes);
36805b261ecSmrg	if (!modes)
36905b261ecSmrg	    return BadAlloc;
37005b261ecSmrg
37105b261ecSmrg	rep.type = X_Reply;
37205b261ecSmrg	rep.sequenceNumber = client->sequence;
37305b261ecSmrg	rep.length = 0;
37405b261ecSmrg	rep.timestamp = pScrPriv->lastSetTime.milliseconds;
37505b261ecSmrg	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
37605b261ecSmrg	rep.nCrtcs = pScrPriv->numCrtcs;
37705b261ecSmrg	rep.nOutputs = pScrPriv->numOutputs;
37805b261ecSmrg	rep.nModes = num_modes;
37905b261ecSmrg	rep.nbytesNames = 0;
38005b261ecSmrg
38105b261ecSmrg	for (i = 0; i < num_modes; i++)
38205b261ecSmrg	    rep.nbytesNames += modes[i]->mode.nameLength;
38305b261ecSmrg
38405b261ecSmrg	rep.length = (pScrPriv->numCrtcs +
38505b261ecSmrg		      pScrPriv->numOutputs +
38605b261ecSmrg		      num_modes * (SIZEOF(xRRModeInfo) >> 2) +
38705b261ecSmrg		      ((rep.nbytesNames + 3) >> 2));
38805b261ecSmrg
38905b261ecSmrg	extraLen = rep.length << 2;
39005b261ecSmrg	if (extraLen)
39105b261ecSmrg	{
39205b261ecSmrg	    extra = xalloc (extraLen);
39305b261ecSmrg	    if (!extra)
39405b261ecSmrg	    {
39505b261ecSmrg		xfree (modes);
39605b261ecSmrg		return BadAlloc;
39705b261ecSmrg	    }
39805b261ecSmrg	}
39905b261ecSmrg	else
40005b261ecSmrg	    extra = NULL;
40105b261ecSmrg
40205b261ecSmrg	crtcs = (RRCrtc *) extra;
40305b261ecSmrg	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
40405b261ecSmrg	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
40505b261ecSmrg	names = (CARD8 *) (modeinfos + num_modes);
40605b261ecSmrg
40705b261ecSmrg	for (i = 0; i < pScrPriv->numCrtcs; i++)
40805b261ecSmrg	{
40905b261ecSmrg	    crtcs[i] = pScrPriv->crtcs[i]->id;
41005b261ecSmrg	    if (client->swapped)
41105b261ecSmrg		swapl (&crtcs[i], n);
41205b261ecSmrg	}
41305b261ecSmrg
41405b261ecSmrg	for (i = 0; i < pScrPriv->numOutputs; i++)
41505b261ecSmrg	{
41605b261ecSmrg	    outputs[i] = pScrPriv->outputs[i]->id;
41705b261ecSmrg	    if (client->swapped)
41805b261ecSmrg		swapl (&outputs[i], n);
41905b261ecSmrg	}
42005b261ecSmrg
42105b261ecSmrg	for (i = 0; i < num_modes; i++)
42205b261ecSmrg	{
42305b261ecSmrg	    RRModePtr	mode = modes[i];
42405b261ecSmrg	    modeinfos[i] = mode->mode;
42505b261ecSmrg	    if (client->swapped)
42605b261ecSmrg	    {
42705b261ecSmrg		swapl (&modeinfos[i].id, n);
42805b261ecSmrg		swaps (&modeinfos[i].width, n);
42905b261ecSmrg		swaps (&modeinfos[i].height, n);
43005b261ecSmrg		swapl (&modeinfos[i].dotClock, n);
43105b261ecSmrg		swaps (&modeinfos[i].hSyncStart, n);
43205b261ecSmrg		swaps (&modeinfos[i].hSyncEnd, n);
43305b261ecSmrg		swaps (&modeinfos[i].hTotal, n);
43405b261ecSmrg		swaps (&modeinfos[i].hSkew, n);
43505b261ecSmrg		swaps (&modeinfos[i].vSyncStart, n);
43605b261ecSmrg		swaps (&modeinfos[i].vSyncEnd, n);
43705b261ecSmrg		swaps (&modeinfos[i].vTotal, n);
43805b261ecSmrg		swaps (&modeinfos[i].nameLength, n);
43905b261ecSmrg		swapl (&modeinfos[i].modeFlags, n);
44005b261ecSmrg	    }
44105b261ecSmrg	    memcpy (names, mode->name,
44205b261ecSmrg		    mode->mode.nameLength);
44305b261ecSmrg	    names += mode->mode.nameLength;
44405b261ecSmrg	}
44505b261ecSmrg    	xfree (modes);
44605b261ecSmrg	assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
44705b261ecSmrg    }
44805b261ecSmrg
44905b261ecSmrg    if (client->swapped) {
45005b261ecSmrg	swaps(&rep.sequenceNumber, n);
45105b261ecSmrg	swapl(&rep.length, n);
45205b261ecSmrg	swapl(&rep.timestamp, n);
45305b261ecSmrg	swapl(&rep.configTimestamp, n);
45405b261ecSmrg	swaps(&rep.nCrtcs, n);
45505b261ecSmrg	swaps(&rep.nOutputs, n);
45605b261ecSmrg	swaps(&rep.nModes, n);
45705b261ecSmrg	swaps(&rep.nbytesNames, n);
45805b261ecSmrg    }
45905b261ecSmrg    WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep);
46005b261ecSmrg    if (extraLen)
46105b261ecSmrg    {
46205b261ecSmrg	WriteToClient (client, extraLen, (char *) extra);
46305b261ecSmrg	xfree (extra);
46405b261ecSmrg    }
46505b261ecSmrg    return client->noClientException;
46605b261ecSmrg}
46705b261ecSmrg
46805b261ecSmrgtypedef struct _RR10Data {
46905b261ecSmrg    RRScreenSizePtr sizes;
47005b261ecSmrg    int		    nsize;
47105b261ecSmrg    int		    nrefresh;
47205b261ecSmrg    int		    size;
47305b261ecSmrg    CARD16	    refresh;
47405b261ecSmrg} RR10DataRec, *RR10DataPtr;
47505b261ecSmrg
47605b261ecSmrg/*
47705b261ecSmrg * Convert 1.2 monitor data into 1.0 screen data
47805b261ecSmrg */
47905b261ecSmrgstatic RR10DataPtr
48005b261ecSmrgRR10GetData (ScreenPtr pScreen, RROutputPtr output)
48105b261ecSmrg{
48205b261ecSmrg    RR10DataPtr	    data;
48305b261ecSmrg    RRScreenSizePtr size;
48405b261ecSmrg    int		    nmode = output->numModes + output->numUserModes;
48505b261ecSmrg    int		    o, os, l, r;
48605b261ecSmrg    RRScreenRatePtr refresh;
48705b261ecSmrg    CARD16	    vRefresh;
48805b261ecSmrg    RRModePtr	    mode;
48905b261ecSmrg    Bool	    *used;
49005b261ecSmrg
49105b261ecSmrg    /* Make sure there is plenty of space for any combination */
49205b261ecSmrg    data = malloc (sizeof (RR10DataRec) +
49305b261ecSmrg		   sizeof (RRScreenSize) * nmode +
49405b261ecSmrg		   sizeof (RRScreenRate) * nmode +
49505b261ecSmrg		   sizeof (Bool) * nmode);
49605b261ecSmrg    if (!data)
49705b261ecSmrg	return NULL;
49805b261ecSmrg    size = (RRScreenSizePtr) (data + 1);
49905b261ecSmrg    refresh = (RRScreenRatePtr) (size + nmode);
50005b261ecSmrg    used = (Bool *) (refresh + nmode);
50105b261ecSmrg    memset (used, '\0', sizeof (Bool) * nmode);
50205b261ecSmrg    data->sizes = size;
50305b261ecSmrg    data->nsize = 0;
50405b261ecSmrg    data->nrefresh = 0;
50505b261ecSmrg    data->size = 0;
50605b261ecSmrg    data->refresh = 0;
50705b261ecSmrg
50805b261ecSmrg    /*
50905b261ecSmrg     * find modes not yet listed
51005b261ecSmrg     */
51105b261ecSmrg    for (o = 0; o < output->numModes + output->numUserModes; o++)
51205b261ecSmrg    {
51305b261ecSmrg	if (used[o]) continue;
51405b261ecSmrg
51505b261ecSmrg	if (o < output->numModes)
51605b261ecSmrg	    mode = output->modes[o];
51705b261ecSmrg	else
51805b261ecSmrg	    mode = output->userModes[o - output->numModes];
51905b261ecSmrg
52005b261ecSmrg	l = data->nsize;
52105b261ecSmrg	size[l].id = data->nsize;
52205b261ecSmrg	size[l].width = mode->mode.width;
52305b261ecSmrg	size[l].height = mode->mode.height;
52405b261ecSmrg	if (output->mmWidth && output->mmHeight) {
52505b261ecSmrg	    size[l].mmWidth = output->mmWidth;
52605b261ecSmrg	    size[l].mmHeight = output->mmHeight;
52705b261ecSmrg	} else {
52805b261ecSmrg	    size[l].mmWidth = pScreen->mmWidth;
52905b261ecSmrg	    size[l].mmHeight = pScreen->mmHeight;
53005b261ecSmrg	}
53105b261ecSmrg	size[l].nRates = 0;
53205b261ecSmrg	size[l].pRates = &refresh[data->nrefresh];
53305b261ecSmrg	data->nsize++;
53405b261ecSmrg
53505b261ecSmrg	/*
53605b261ecSmrg	 * Find all modes with matching size
53705b261ecSmrg	 */
53805b261ecSmrg	for (os = o; os < output->numModes + output->numUserModes; os++)
53905b261ecSmrg	{
54005b261ecSmrg	    if (os < output->numModes)
54105b261ecSmrg		mode = output->modes[os];
54205b261ecSmrg	    else
54305b261ecSmrg		mode = output->userModes[os - output->numModes];
54405b261ecSmrg	    if (mode->mode.width == size[l].width &&
54505b261ecSmrg		mode->mode.height == size[l].height)
54605b261ecSmrg	    {
54705b261ecSmrg		vRefresh = RRVerticalRefresh (&mode->mode);
54805b261ecSmrg		used[os] = TRUE;
54905b261ecSmrg
55005b261ecSmrg		for (r = 0; r < size[l].nRates; r++)
55105b261ecSmrg		    if (vRefresh == size[l].pRates[r].rate)
55205b261ecSmrg			break;
55305b261ecSmrg		if (r == size[l].nRates)
55405b261ecSmrg		{
55505b261ecSmrg		    size[l].pRates[r].rate = vRefresh;
55605b261ecSmrg		    size[l].pRates[r].mode = mode;
55705b261ecSmrg		    size[l].nRates++;
55805b261ecSmrg		    data->nrefresh++;
55905b261ecSmrg		}
56005b261ecSmrg		if (mode == output->crtc->mode)
56105b261ecSmrg		{
56205b261ecSmrg		    data->size = l;
56305b261ecSmrg		    data->refresh = vRefresh;
56405b261ecSmrg		}
56505b261ecSmrg	    }
56605b261ecSmrg	}
56705b261ecSmrg    }
56805b261ecSmrg    return data;
56905b261ecSmrg}
57005b261ecSmrg
57105b261ecSmrgint
57205b261ecSmrgProcRRGetScreenInfo (ClientPtr client)
57305b261ecSmrg{
57405b261ecSmrg    REQUEST(xRRGetScreenInfoReq);
57505b261ecSmrg    xRRGetScreenInfoReply   rep;
57605b261ecSmrg    WindowPtr	    	    pWin;
57705b261ecSmrg    int			    n, rc;
57805b261ecSmrg    ScreenPtr		    pScreen;
57905b261ecSmrg    rrScrPrivPtr	    pScrPriv;
58005b261ecSmrg    CARD8		    *extra;
58105b261ecSmrg    unsigned long	    extraLen;
58205b261ecSmrg    RROutputPtr		    output;
58305b261ecSmrg
58405b261ecSmrg    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
58505b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
58605b261ecSmrg    if (rc != Success)
58705b261ecSmrg	return rc;
58805b261ecSmrg
58905b261ecSmrg    pScreen = pWin->drawable.pScreen;
59005b261ecSmrg    pScrPriv = rrGetScrPriv(pScreen);
59105b261ecSmrg    rep.pad = 0;
59205b261ecSmrg
59305b261ecSmrg    if (pScrPriv)
59405b261ecSmrg	if (!RRGetInfo (pScreen))
59505b261ecSmrg	    return BadAlloc;
59605b261ecSmrg
59705b261ecSmrg    output = RRFirstOutput (pScreen);
59805b261ecSmrg
59905b261ecSmrg    if (!pScrPriv || !output)
60005b261ecSmrg    {
60105b261ecSmrg	rep.type = X_Reply;
60205b261ecSmrg	rep.setOfRotations = RR_Rotate_0;;
60305b261ecSmrg	rep.sequenceNumber = client->sequence;
60405b261ecSmrg	rep.length = 0;
60505b261ecSmrg	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
60605b261ecSmrg	rep.timestamp = currentTime.milliseconds;
60705b261ecSmrg	rep.configTimestamp = currentTime.milliseconds;
60805b261ecSmrg	rep.nSizes = 0;
60905b261ecSmrg	rep.sizeID = 0;
61005b261ecSmrg	rep.rotation = RR_Rotate_0;
61105b261ecSmrg	rep.rate = 0;
61205b261ecSmrg	rep.nrateEnts = 0;
61305b261ecSmrg	extra = 0;
61405b261ecSmrg	extraLen = 0;
61505b261ecSmrg    }
61605b261ecSmrg    else
61705b261ecSmrg    {
61805b261ecSmrg	int			i, j;
61905b261ecSmrg	xScreenSizes		*size;
62005b261ecSmrg	CARD16			*rates;
62105b261ecSmrg	CARD8			*data8;
62205b261ecSmrg	Bool			has_rate = RRClientKnowsRates (client);
62305b261ecSmrg	RR10DataPtr		pData;
62405b261ecSmrg	RRScreenSizePtr		pSize;
62505b261ecSmrg
62605b261ecSmrg	pData = RR10GetData (pScreen, output);
62705b261ecSmrg	if (!pData)
62805b261ecSmrg	    return BadAlloc;
62905b261ecSmrg
63005b261ecSmrg	rep.type = X_Reply;
63105b261ecSmrg	rep.setOfRotations = output->crtc->rotations;
63205b261ecSmrg	rep.sequenceNumber = client->sequence;
63305b261ecSmrg	rep.length = 0;
63405b261ecSmrg	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
63505b261ecSmrg	rep.timestamp = pScrPriv->lastSetTime.milliseconds;
63605b261ecSmrg	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
63705b261ecSmrg	rep.rotation = output->crtc->rotation;
63805b261ecSmrg	rep.nSizes = pData->nsize;
63905b261ecSmrg        rep.nrateEnts = pData->nrefresh + pData->nsize;
64005b261ecSmrg	rep.sizeID = pData->size;
64105b261ecSmrg	rep.rate = pData->refresh;
64205b261ecSmrg
64305b261ecSmrg	extraLen = (rep.nSizes * sizeof (xScreenSizes) +
64405b261ecSmrg		    rep.nrateEnts * sizeof (CARD16));
64505b261ecSmrg
64605b261ecSmrg	if (extraLen)
64705b261ecSmrg	{
64805b261ecSmrg	    extra = (CARD8 *) xalloc (extraLen);
64905b261ecSmrg	    if (!extra)
65005b261ecSmrg	    {
65105b261ecSmrg		xfree (pData);
65205b261ecSmrg		return BadAlloc;
65305b261ecSmrg	    }
65405b261ecSmrg	}
65505b261ecSmrg	else
65605b261ecSmrg	    extra = NULL;
65705b261ecSmrg
65805b261ecSmrg	/*
65905b261ecSmrg	 * First comes the size information
66005b261ecSmrg	 */
66105b261ecSmrg	size = (xScreenSizes *) extra;
66205b261ecSmrg	rates = (CARD16 *) (size + rep.nSizes);
66305b261ecSmrg	for (i = 0; i < pData->nsize; i++)
66405b261ecSmrg	{
66505b261ecSmrg	    pSize = &pData->sizes[i];
66605b261ecSmrg	    size->widthInPixels = pSize->width;
66705b261ecSmrg	    size->heightInPixels = pSize->height;
66805b261ecSmrg	    size->widthInMillimeters = pSize->mmWidth;
66905b261ecSmrg	    size->heightInMillimeters = pSize->mmHeight;
67005b261ecSmrg	    if (client->swapped)
67105b261ecSmrg	    {
67205b261ecSmrg	        swaps (&size->widthInPixels, n);
67305b261ecSmrg	        swaps (&size->heightInPixels, n);
67405b261ecSmrg	        swaps (&size->widthInMillimeters, n);
67505b261ecSmrg	        swaps (&size->heightInMillimeters, n);
67605b261ecSmrg	    }
67705b261ecSmrg	    size++;
67805b261ecSmrg	    if (has_rate)
67905b261ecSmrg	    {
68005b261ecSmrg		*rates = pSize->nRates;
68105b261ecSmrg		if (client->swapped)
68205b261ecSmrg		{
68305b261ecSmrg		    swaps (rates, n);
68405b261ecSmrg		}
68505b261ecSmrg		rates++;
68605b261ecSmrg		for (j = 0; j < pSize->nRates; j++)
68705b261ecSmrg		{
68805b261ecSmrg		    *rates = pSize->pRates[j].rate;
68905b261ecSmrg		    if (client->swapped)
69005b261ecSmrg		    {
69105b261ecSmrg			swaps (rates, n);
69205b261ecSmrg		    }
69305b261ecSmrg		    rates++;
69405b261ecSmrg		}
69505b261ecSmrg	    }
69605b261ecSmrg	}
69705b261ecSmrg        xfree (pData);
69805b261ecSmrg
69905b261ecSmrg	data8 = (CARD8 *) rates;
70005b261ecSmrg
70105b261ecSmrg	if (data8 - (CARD8 *) extra != extraLen)
70205b261ecSmrg	    FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
70305b261ecSmrg			(unsigned long)(data8 - (CARD8 *) extra), extraLen);
70405b261ecSmrg	rep.length =  (extraLen + 3) >> 2;
70505b261ecSmrg    }
70605b261ecSmrg    if (client->swapped) {
70705b261ecSmrg	swaps(&rep.sequenceNumber, n);
70805b261ecSmrg	swapl(&rep.length, n);
70905b261ecSmrg	swapl(&rep.timestamp, n);
71005b261ecSmrg	swaps(&rep.rotation, n);
71105b261ecSmrg	swaps(&rep.nSizes, n);
71205b261ecSmrg	swaps(&rep.sizeID, n);
71305b261ecSmrg	swaps(&rep.rate, n);
71405b261ecSmrg	swaps(&rep.nrateEnts, n);
71505b261ecSmrg    }
71605b261ecSmrg    WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
71705b261ecSmrg    if (extraLen)
71805b261ecSmrg    {
71905b261ecSmrg	WriteToClient (client, extraLen, (char *) extra);
72005b261ecSmrg	xfree (extra);
72105b261ecSmrg    }
72205b261ecSmrg    return (client->noClientException);
72305b261ecSmrg}
72405b261ecSmrg
72505b261ecSmrgint
72605b261ecSmrgProcRRSetScreenConfig (ClientPtr client)
72705b261ecSmrg{
72805b261ecSmrg    REQUEST(xRRSetScreenConfigReq);
72905b261ecSmrg    xRRSetScreenConfigReply rep;
73005b261ecSmrg    DrawablePtr		    pDraw;
73105b261ecSmrg    int			    n, rc;
73205b261ecSmrg    ScreenPtr		    pScreen;
73305b261ecSmrg    rrScrPrivPtr	    pScrPriv;
73405b261ecSmrg    TimeStamp		    configTime;
73505b261ecSmrg    TimeStamp		    time;
73605b261ecSmrg    int			    i;
73705b261ecSmrg    Rotation		    rotation;
73805b261ecSmrg    int			    rate;
73905b261ecSmrg    Bool		    has_rate;
74005b261ecSmrg    RROutputPtr		    output;
74105b261ecSmrg    RRCrtcPtr		    crtc;
74205b261ecSmrg    RRModePtr		    mode;
74305b261ecSmrg    RR10DataPtr		    pData = NULL;
74405b261ecSmrg    RRScreenSizePtr    	    pSize;
74505b261ecSmrg    int			    width, height;
74605b261ecSmrg
74705b261ecSmrg    UpdateCurrentTime ();
74805b261ecSmrg
74905b261ecSmrg    if (RRClientKnowsRates (client))
75005b261ecSmrg    {
75105b261ecSmrg	REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
75205b261ecSmrg	has_rate = TRUE;
75305b261ecSmrg    }
75405b261ecSmrg    else
75505b261ecSmrg    {
75605b261ecSmrg	REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
75705b261ecSmrg	has_rate = FALSE;
75805b261ecSmrg    }
75905b261ecSmrg
76005b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess);
76105b261ecSmrg    if (rc != Success)
76205b261ecSmrg	return rc;
76305b261ecSmrg
76405b261ecSmrg    pScreen = pDraw->pScreen;
76505b261ecSmrg
76605b261ecSmrg    pScrPriv = rrGetScrPriv(pScreen);
76705b261ecSmrg
76805b261ecSmrg    time = ClientTimeToServerTime(stuff->timestamp);
76905b261ecSmrg
77005b261ecSmrg    if (!pScrPriv)
77105b261ecSmrg    {
77205b261ecSmrg	time = currentTime;
77305b261ecSmrg	rep.status = RRSetConfigFailed;
77405b261ecSmrg	goto sendReply;
77505b261ecSmrg    }
77605b261ecSmrg    if (!RRGetInfo (pScreen))
77705b261ecSmrg	return BadAlloc;
77805b261ecSmrg
77905b261ecSmrg    output = RRFirstOutput (pScreen);
78005b261ecSmrg    if (!output)
78105b261ecSmrg    {
78205b261ecSmrg	time = currentTime;
78305b261ecSmrg	rep.status = RRSetConfigFailed;
78405b261ecSmrg	goto sendReply;
78505b261ecSmrg    }
78605b261ecSmrg
78705b261ecSmrg    crtc = output->crtc;
78805b261ecSmrg
78905b261ecSmrg    /*
79005b261ecSmrg     * If the client's config timestamp is not the same as the last config
79105b261ecSmrg     * timestamp, then the config information isn't up-to-date and
79205b261ecSmrg     * can't even be validated.
79305b261ecSmrg     *
79405b261ecSmrg     * Note that the client only knows about the milliseconds part of the
79505b261ecSmrg     * timestamp, so using CompareTimeStamps here would cause randr to suddenly
79605b261ecSmrg     * stop working after several hours have passed (freedesktop bug #6502).
79705b261ecSmrg     */
79805b261ecSmrg    if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds)
79905b261ecSmrg    {
80005b261ecSmrg	rep.status = RRSetConfigInvalidConfigTime;
80105b261ecSmrg	goto sendReply;
80205b261ecSmrg    }
80305b261ecSmrg
80405b261ecSmrg    pData = RR10GetData (pScreen, output);
80505b261ecSmrg    if (!pData)
80605b261ecSmrg	return BadAlloc;
80705b261ecSmrg
80805b261ecSmrg    if (stuff->sizeID >= pData->nsize)
80905b261ecSmrg    {
81005b261ecSmrg	/*
81105b261ecSmrg	 * Invalid size ID
81205b261ecSmrg	 */
81305b261ecSmrg	client->errorValue = stuff->sizeID;
81405b261ecSmrg	xfree (pData);
81505b261ecSmrg	return BadValue;
81605b261ecSmrg    }
81705b261ecSmrg    pSize = &pData->sizes[stuff->sizeID];
81805b261ecSmrg
81905b261ecSmrg    /*
82005b261ecSmrg     * Validate requested rotation
82105b261ecSmrg     */
82205b261ecSmrg    rotation = (Rotation) stuff->rotation;
82305b261ecSmrg
82405b261ecSmrg    /* test the rotation bits only! */
82505b261ecSmrg    switch (rotation & 0xf) {
82605b261ecSmrg    case RR_Rotate_0:
82705b261ecSmrg    case RR_Rotate_90:
82805b261ecSmrg    case RR_Rotate_180:
82905b261ecSmrg    case RR_Rotate_270:
83005b261ecSmrg	break;
83105b261ecSmrg    default:
83205b261ecSmrg	/*
83305b261ecSmrg	 * Invalid rotation
83405b261ecSmrg	 */
83505b261ecSmrg	client->errorValue = stuff->rotation;
83605b261ecSmrg	xfree (pData);
83705b261ecSmrg	return BadValue;
83805b261ecSmrg    }
83905b261ecSmrg
84005b261ecSmrg    if ((~crtc->rotations) & rotation)
84105b261ecSmrg    {
84205b261ecSmrg	/*
84305b261ecSmrg	 * requested rotation or reflection not supported by screen
84405b261ecSmrg	 */
84505b261ecSmrg	client->errorValue = stuff->rotation;
84605b261ecSmrg	xfree (pData);
84705b261ecSmrg	return BadMatch;
84805b261ecSmrg    }
84905b261ecSmrg
85005b261ecSmrg    /*
85105b261ecSmrg     * Validate requested refresh
85205b261ecSmrg     */
85305b261ecSmrg    if (has_rate)
85405b261ecSmrg	rate = (int) stuff->rate;
85505b261ecSmrg    else
85605b261ecSmrg	rate = 0;
85705b261ecSmrg
85805b261ecSmrg    if (rate)
85905b261ecSmrg    {
86005b261ecSmrg	for (i = 0; i < pSize->nRates; i++)
86105b261ecSmrg	{
86205b261ecSmrg	    if (pSize->pRates[i].rate == rate)
86305b261ecSmrg		break;
86405b261ecSmrg	}
86505b261ecSmrg	if (i == pSize->nRates)
86605b261ecSmrg	{
86705b261ecSmrg	    /*
86805b261ecSmrg	     * Invalid rate
86905b261ecSmrg	     */
87005b261ecSmrg	    client->errorValue = rate;
87105b261ecSmrg	    xfree (pData);
87205b261ecSmrg	    return BadValue;
87305b261ecSmrg	}
87405b261ecSmrg	mode = pSize->pRates[i].mode;
87505b261ecSmrg    }
87605b261ecSmrg    else
87705b261ecSmrg	mode = pSize->pRates[0].mode;
87805b261ecSmrg
87905b261ecSmrg    /*
88005b261ecSmrg     * Make sure the requested set-time is not older than
88105b261ecSmrg     * the last set-time
88205b261ecSmrg     */
88305b261ecSmrg    if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
88405b261ecSmrg    {
88505b261ecSmrg	rep.status = RRSetConfigInvalidTime;
88605b261ecSmrg	goto sendReply;
88705b261ecSmrg    }
88805b261ecSmrg
88905b261ecSmrg    /*
89005b261ecSmrg     * If the screen size is changing, adjust all of the other outputs
89105b261ecSmrg     * to fit the new size, mirroring as much as possible
89205b261ecSmrg     */
89305b261ecSmrg    width = mode->mode.width;
89405b261ecSmrg    height = mode->mode.height;
89505b261ecSmrg    if (rotation & (RR_Rotate_90|RR_Rotate_270))
89605b261ecSmrg    {
89705b261ecSmrg	width = mode->mode.height;
89805b261ecSmrg	height = mode->mode.width;
89905b261ecSmrg    }
90005b261ecSmrg    if (width != pScreen->width || height != pScreen->height)
90105b261ecSmrg    {
90205b261ecSmrg	int	c;
90305b261ecSmrg
90405b261ecSmrg	for (c = 0; c < pScrPriv->numCrtcs; c++)
90505b261ecSmrg	{
90605b261ecSmrg	    if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
90705b261ecSmrg			    0, NULL))
90805b261ecSmrg	    {
90905b261ecSmrg		rep.status = RRSetConfigFailed;
91005b261ecSmrg		/* XXX recover from failure */
91105b261ecSmrg		goto sendReply;
91205b261ecSmrg	    }
91305b261ecSmrg	}
91405b261ecSmrg	if (!RRScreenSizeSet (pScreen, width, height,
91505b261ecSmrg			      pScreen->mmWidth, pScreen->mmHeight))
91605b261ecSmrg	{
91705b261ecSmrg	    rep.status = RRSetConfigFailed;
91805b261ecSmrg	    /* XXX recover from failure */
91905b261ecSmrg	    goto sendReply;
92005b261ecSmrg	}
92105b261ecSmrg    }
92205b261ecSmrg
92305b261ecSmrg    if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output))
92405b261ecSmrg	rep.status = RRSetConfigFailed;
92505b261ecSmrg    else
92605b261ecSmrg	rep.status = RRSetConfigSuccess;
92705b261ecSmrg
92805b261ecSmrg    /*
92905b261ecSmrg     * XXX Configure other crtcs to mirror as much as possible
93005b261ecSmrg     */
93105b261ecSmrg
93205b261ecSmrgsendReply:
93305b261ecSmrg
93405b261ecSmrg    if (pData)
93505b261ecSmrg	xfree (pData);
93605b261ecSmrg
93705b261ecSmrg    rep.type = X_Reply;
93805b261ecSmrg    /* rep.status has already been filled in */
93905b261ecSmrg    rep.length = 0;
94005b261ecSmrg    rep.sequenceNumber = client->sequence;
94105b261ecSmrg
94205b261ecSmrg    rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
94305b261ecSmrg    rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
94405b261ecSmrg    rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
94505b261ecSmrg
94605b261ecSmrg    if (client->swapped)
94705b261ecSmrg    {
94805b261ecSmrg    	swaps(&rep.sequenceNumber, n);
94905b261ecSmrg    	swapl(&rep.length, n);
95005b261ecSmrg	swapl(&rep.newTimestamp, n);
95105b261ecSmrg	swapl(&rep.newConfigTimestamp, n);
95205b261ecSmrg	swapl(&rep.root, n);
95305b261ecSmrg    }
95405b261ecSmrg    WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
95505b261ecSmrg
95605b261ecSmrg    return (client->noClientException);
95705b261ecSmrg}
95805b261ecSmrg
95905b261ecSmrgstatic CARD16
96005b261ecSmrgRR10CurrentSizeID (ScreenPtr pScreen)
96105b261ecSmrg{
96205b261ecSmrg    CARD16	sizeID = 0xffff;
96305b261ecSmrg    RROutputPtr output = RRFirstOutput (pScreen);
96405b261ecSmrg
96505b261ecSmrg    if (output)
96605b261ecSmrg    {
96705b261ecSmrg	RR10DataPtr data = RR10GetData (pScreen, output);
96805b261ecSmrg	if (data)
96905b261ecSmrg	{
97005b261ecSmrg	    int i;
97105b261ecSmrg	    for (i = 0; i < data->nsize; i++)
97205b261ecSmrg		if (data->sizes[i].width == pScreen->width &&
97305b261ecSmrg		    data->sizes[i].height == pScreen->height)
97405b261ecSmrg		{
97505b261ecSmrg		    sizeID = (CARD16) i;
97605b261ecSmrg		    break;
97705b261ecSmrg		}
97805b261ecSmrg	    xfree (data);
97905b261ecSmrg	}
98005b261ecSmrg    }
98105b261ecSmrg    return sizeID;
98205b261ecSmrg}
983