1706f2543Smrg/* 2706f2543Smrg * Copyright © 2006 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 7706f2543Smrg * notice and this permission notice appear in supporting documentation, and 8706f2543Smrg * that the name of the copyright holders not be used in advertising or 9706f2543Smrg * publicity pertaining to distribution of the software without specific, 10706f2543Smrg * written prior permission. The copyright holders make no representations 11706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 12706f2543Smrg * is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20706f2543Smrg * OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#include "randrstr.h" 24706f2543Smrg 25706f2543Smrgstatic const int padlength[4] = {0, 3, 2, 1}; 26706f2543Smrg 27706f2543Smrgstatic CARD16 28706f2543SmrgRR10CurrentSizeID (ScreenPtr pScreen); 29706f2543Smrg 30706f2543Smrg/* 31706f2543Smrg * Edit connection information block so that new clients 32706f2543Smrg * see the current screen size on connect 33706f2543Smrg */ 34706f2543Smrgstatic void 35706f2543SmrgRREditConnectionInfo (ScreenPtr pScreen) 36706f2543Smrg{ 37706f2543Smrg xConnSetup *connSetup; 38706f2543Smrg char *vendor; 39706f2543Smrg xPixmapFormat *formats; 40706f2543Smrg xWindowRoot *root; 41706f2543Smrg xDepth *depth; 42706f2543Smrg xVisualType *visual; 43706f2543Smrg int screen = 0; 44706f2543Smrg int d; 45706f2543Smrg 46706f2543Smrg connSetup = (xConnSetup *) ConnectionInfo; 47706f2543Smrg vendor = (char *) connSetup + sizeof (xConnSetup); 48706f2543Smrg formats = (xPixmapFormat *) ((char *) vendor + 49706f2543Smrg connSetup->nbytesVendor + 50706f2543Smrg padlength[connSetup->nbytesVendor & 3]); 51706f2543Smrg root = (xWindowRoot *) ((char *) formats + 52706f2543Smrg sizeof (xPixmapFormat) * screenInfo.numPixmapFormats); 53706f2543Smrg while (screen != pScreen->myNum) 54706f2543Smrg { 55706f2543Smrg depth = (xDepth *) ((char *) root + 56706f2543Smrg sizeof (xWindowRoot)); 57706f2543Smrg for (d = 0; d < root->nDepths; d++) 58706f2543Smrg { 59706f2543Smrg visual = (xVisualType *) ((char *) depth + 60706f2543Smrg sizeof (xDepth)); 61706f2543Smrg depth = (xDepth *) ((char *) visual + 62706f2543Smrg depth->nVisuals * sizeof (xVisualType)); 63706f2543Smrg } 64706f2543Smrg root = (xWindowRoot *) ((char *) depth); 65706f2543Smrg screen++; 66706f2543Smrg } 67706f2543Smrg root->pixWidth = pScreen->width; 68706f2543Smrg root->pixHeight = pScreen->height; 69706f2543Smrg root->mmWidth = pScreen->mmWidth; 70706f2543Smrg root->mmHeight = pScreen->mmHeight; 71706f2543Smrg} 72706f2543Smrg 73706f2543Smrgvoid 74706f2543SmrgRRSendConfigNotify (ScreenPtr pScreen) 75706f2543Smrg{ 76706f2543Smrg WindowPtr pWin = pScreen->root; 77706f2543Smrg xEvent event; 78706f2543Smrg 79706f2543Smrg event.u.u.type = ConfigureNotify; 80706f2543Smrg event.u.configureNotify.window = pWin->drawable.id; 81706f2543Smrg event.u.configureNotify.aboveSibling = None; 82706f2543Smrg event.u.configureNotify.x = 0; 83706f2543Smrg event.u.configureNotify.y = 0; 84706f2543Smrg 85706f2543Smrg /* XXX xinerama stuff ? */ 86706f2543Smrg 87706f2543Smrg event.u.configureNotify.width = pWin->drawable.width; 88706f2543Smrg event.u.configureNotify.height = pWin->drawable.height; 89706f2543Smrg event.u.configureNotify.borderWidth = wBorderWidth (pWin); 90706f2543Smrg event.u.configureNotify.override = pWin->overrideRedirect; 91706f2543Smrg DeliverEvents(pWin, &event, 1, NullWindow); 92706f2543Smrg} 93706f2543Smrg 94706f2543Smrgvoid 95706f2543SmrgRRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) 96706f2543Smrg{ 97706f2543Smrg rrScrPriv (pScreen); 98706f2543Smrg xRRScreenChangeNotifyEvent se; 99706f2543Smrg RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL; 100706f2543Smrg WindowPtr pRoot = pScreen->root; 101706f2543Smrg 102706f2543Smrg se.type = RRScreenChangeNotify + RREventBase; 103706f2543Smrg se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); 104706f2543Smrg se.timestamp = pScrPriv->lastSetTime.milliseconds; 105706f2543Smrg se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 106706f2543Smrg se.root = pRoot->drawable.id; 107706f2543Smrg se.window = pWin->drawable.id; 108706f2543Smrg se.subpixelOrder = PictureGetSubpixelOrder (pScreen); 109706f2543Smrg 110706f2543Smrg se.sizeID = RR10CurrentSizeID (pScreen); 111706f2543Smrg 112706f2543Smrg if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { 113706f2543Smrg se.widthInPixels = pScreen->height; 114706f2543Smrg se.heightInPixels = pScreen->width; 115706f2543Smrg se.widthInMillimeters = pScreen->mmHeight; 116706f2543Smrg se.heightInMillimeters = pScreen->mmWidth; 117706f2543Smrg } else { 118706f2543Smrg se.widthInPixels = pScreen->width; 119706f2543Smrg se.heightInPixels = pScreen->height; 120706f2543Smrg se.widthInMillimeters = pScreen->mmWidth; 121706f2543Smrg se.heightInMillimeters = pScreen->mmHeight; 122706f2543Smrg } 123706f2543Smrg 124706f2543Smrg WriteEventsToClient (client, 1, (xEvent *) &se); 125706f2543Smrg} 126706f2543Smrg 127706f2543Smrg/* 128706f2543Smrg * Notify the extension that the screen size has been changed. 129706f2543Smrg * The driver is responsible for calling this whenever it has changed 130706f2543Smrg * the size of the screen 131706f2543Smrg */ 132706f2543Smrgvoid 133706f2543SmrgRRScreenSizeNotify (ScreenPtr pScreen) 134706f2543Smrg{ 135706f2543Smrg rrScrPriv(pScreen); 136706f2543Smrg /* 137706f2543Smrg * Deliver ConfigureNotify events when root changes 138706f2543Smrg * pixel size 139706f2543Smrg */ 140706f2543Smrg if (pScrPriv->width == pScreen->width && 141706f2543Smrg pScrPriv->height == pScreen->height && 142706f2543Smrg pScrPriv->mmWidth == pScreen->mmWidth && 143706f2543Smrg pScrPriv->mmHeight == pScreen->mmHeight) 144706f2543Smrg return; 145706f2543Smrg 146706f2543Smrg pScrPriv->width = pScreen->width; 147706f2543Smrg pScrPriv->height = pScreen->height; 148706f2543Smrg pScrPriv->mmWidth = pScreen->mmWidth; 149706f2543Smrg pScrPriv->mmHeight = pScreen->mmHeight; 150706f2543Smrg pScrPriv->changed = TRUE; 151706f2543Smrg/* pScrPriv->sizeChanged = TRUE; */ 152706f2543Smrg 153706f2543Smrg RRTellChanged (pScreen); 154706f2543Smrg RRSendConfigNotify (pScreen); 155706f2543Smrg RREditConnectionInfo (pScreen); 156706f2543Smrg 157706f2543Smrg RRPointerScreenConfigured (pScreen); 158706f2543Smrg /* 159706f2543Smrg * Fix pointer bounds and location 160706f2543Smrg */ 161706f2543Smrg ScreenRestructured (pScreen); 162706f2543Smrg} 163706f2543Smrg 164706f2543Smrg/* 165706f2543Smrg * Request that the screen be resized 166706f2543Smrg */ 167706f2543SmrgBool 168706f2543SmrgRRScreenSizeSet (ScreenPtr pScreen, 169706f2543Smrg CARD16 width, 170706f2543Smrg CARD16 height, 171706f2543Smrg CARD32 mmWidth, 172706f2543Smrg CARD32 mmHeight) 173706f2543Smrg{ 174706f2543Smrg rrScrPriv(pScreen); 175706f2543Smrg 176706f2543Smrg#if RANDR_12_INTERFACE 177706f2543Smrg if (pScrPriv->rrScreenSetSize) 178706f2543Smrg { 179706f2543Smrg return (*pScrPriv->rrScreenSetSize) (pScreen, 180706f2543Smrg width, height, 181706f2543Smrg mmWidth, mmHeight); 182706f2543Smrg } 183706f2543Smrg#endif 184706f2543Smrg#if RANDR_10_INTERFACE 185706f2543Smrg if (pScrPriv->rrSetConfig) 186706f2543Smrg { 187706f2543Smrg return TRUE; /* can't set size separately */ 188706f2543Smrg } 189706f2543Smrg#endif 190706f2543Smrg return FALSE; 191706f2543Smrg} 192706f2543Smrg 193706f2543Smrg/* 194706f2543Smrg * Retrieve valid screen size range 195706f2543Smrg */ 196706f2543Smrgint 197706f2543SmrgProcRRGetScreenSizeRange (ClientPtr client) 198706f2543Smrg{ 199706f2543Smrg REQUEST(xRRGetScreenSizeRangeReq); 200706f2543Smrg xRRGetScreenSizeRangeReply rep; 201706f2543Smrg WindowPtr pWin; 202706f2543Smrg ScreenPtr pScreen; 203706f2543Smrg rrScrPrivPtr pScrPriv; 204706f2543Smrg int rc; 205706f2543Smrg 206706f2543Smrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 207706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 208706f2543Smrg if (rc != Success) 209706f2543Smrg return rc; 210706f2543Smrg 211706f2543Smrg pScreen = pWin->drawable.pScreen; 212706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 213706f2543Smrg 214706f2543Smrg rep.type = X_Reply; 215706f2543Smrg rep.pad = 0; 216706f2543Smrg rep.sequenceNumber = client->sequence; 217706f2543Smrg rep.length = 0; 218706f2543Smrg 219706f2543Smrg if (pScrPriv) 220706f2543Smrg { 221706f2543Smrg if (!RRGetInfo (pScreen, FALSE)) 222706f2543Smrg return BadAlloc; 223706f2543Smrg rep.minWidth = pScrPriv->minWidth; 224706f2543Smrg rep.minHeight = pScrPriv->minHeight; 225706f2543Smrg rep.maxWidth = pScrPriv->maxWidth; 226706f2543Smrg rep.maxHeight = pScrPriv->maxHeight; 227706f2543Smrg } 228706f2543Smrg else 229706f2543Smrg { 230706f2543Smrg rep.maxWidth = rep.minWidth = pScreen->width; 231706f2543Smrg rep.maxHeight = rep.minHeight = pScreen->height; 232706f2543Smrg } 233706f2543Smrg if (client->swapped) 234706f2543Smrg { 235706f2543Smrg int n; 236706f2543Smrg 237706f2543Smrg swaps(&rep.sequenceNumber, n); 238706f2543Smrg swapl(&rep.length, n); 239706f2543Smrg swaps(&rep.minWidth, n); 240706f2543Smrg swaps(&rep.minHeight, n); 241706f2543Smrg swaps(&rep.maxWidth, n); 242706f2543Smrg swaps(&rep.maxHeight, n); 243706f2543Smrg } 244706f2543Smrg WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep); 245706f2543Smrg return Success; 246706f2543Smrg} 247706f2543Smrg 248706f2543Smrgint 249706f2543SmrgProcRRSetScreenSize (ClientPtr client) 250706f2543Smrg{ 251706f2543Smrg REQUEST(xRRSetScreenSizeReq); 252706f2543Smrg WindowPtr pWin; 253706f2543Smrg ScreenPtr pScreen; 254706f2543Smrg rrScrPrivPtr pScrPriv; 255706f2543Smrg int i, rc; 256706f2543Smrg 257706f2543Smrg REQUEST_SIZE_MATCH(xRRSetScreenSizeReq); 258706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 259706f2543Smrg if (rc != Success) 260706f2543Smrg return rc; 261706f2543Smrg 262706f2543Smrg pScreen = pWin->drawable.pScreen; 263706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 264706f2543Smrg if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) 265706f2543Smrg { 266706f2543Smrg client->errorValue = stuff->width; 267706f2543Smrg return BadValue; 268706f2543Smrg } 269706f2543Smrg if (stuff->height < pScrPriv->minHeight || 270706f2543Smrg pScrPriv->maxHeight < stuff->height) 271706f2543Smrg { 272706f2543Smrg client->errorValue = stuff->height; 273706f2543Smrg return BadValue; 274706f2543Smrg } 275706f2543Smrg for (i = 0; i < pScrPriv->numCrtcs; i++) 276706f2543Smrg { 277706f2543Smrg RRCrtcPtr crtc = pScrPriv->crtcs[i]; 278706f2543Smrg RRModePtr mode = crtc->mode; 279706f2543Smrg if (mode) 280706f2543Smrg { 281706f2543Smrg int source_width = mode->mode.width; 282706f2543Smrg int source_height = mode->mode.height; 283706f2543Smrg Rotation rotation = crtc->rotation; 284706f2543Smrg 285706f2543Smrg if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270) 286706f2543Smrg { 287706f2543Smrg source_width = mode->mode.height; 288706f2543Smrg source_height = mode->mode.width; 289706f2543Smrg } 290706f2543Smrg 291706f2543Smrg if (crtc->x + source_width > stuff->width || 292706f2543Smrg crtc->y + source_height > stuff->height) 293706f2543Smrg return BadMatch; 294706f2543Smrg } 295706f2543Smrg } 296706f2543Smrg if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) 297706f2543Smrg { 298706f2543Smrg client->errorValue = 0; 299706f2543Smrg return BadValue; 300706f2543Smrg } 301706f2543Smrg if (!RRScreenSizeSet (pScreen, 302706f2543Smrg stuff->width, stuff->height, 303706f2543Smrg stuff->widthInMillimeters, 304706f2543Smrg stuff->heightInMillimeters)) 305706f2543Smrg { 306706f2543Smrg return BadMatch; 307706f2543Smrg } 308706f2543Smrg return Success; 309706f2543Smrg} 310706f2543Smrg 311706f2543Smrgstatic int 312706f2543SmrgrrGetScreenResources(ClientPtr client, Bool query) 313706f2543Smrg{ 314706f2543Smrg REQUEST(xRRGetScreenResourcesReq); 315706f2543Smrg xRRGetScreenResourcesReply rep; 316706f2543Smrg WindowPtr pWin; 317706f2543Smrg ScreenPtr pScreen; 318706f2543Smrg rrScrPrivPtr pScrPriv; 319706f2543Smrg CARD8 *extra; 320706f2543Smrg unsigned long extraLen; 321706f2543Smrg int i, n, rc, has_primary = 0; 322706f2543Smrg RRCrtc *crtcs; 323706f2543Smrg RROutput *outputs; 324706f2543Smrg xRRModeInfo *modeinfos; 325706f2543Smrg CARD8 *names; 326706f2543Smrg 327706f2543Smrg REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); 328706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 329706f2543Smrg if (rc != Success) 330706f2543Smrg return rc; 331706f2543Smrg 332706f2543Smrg pScreen = pWin->drawable.pScreen; 333706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 334706f2543Smrg rep.pad = 0; 335706f2543Smrg 336706f2543Smrg if (query && pScrPriv) 337706f2543Smrg if (!RRGetInfo (pScreen, query)) 338706f2543Smrg return BadAlloc; 339706f2543Smrg 340706f2543Smrg if (!pScrPriv) 341706f2543Smrg { 342706f2543Smrg rep.type = X_Reply; 343706f2543Smrg rep.sequenceNumber = client->sequence; 344706f2543Smrg rep.length = 0; 345706f2543Smrg rep.timestamp = currentTime.milliseconds; 346706f2543Smrg rep.configTimestamp = currentTime.milliseconds; 347706f2543Smrg rep.nCrtcs = 0; 348706f2543Smrg rep.nOutputs = 0; 349706f2543Smrg rep.nModes = 0; 350706f2543Smrg rep.nbytesNames = 0; 351706f2543Smrg extra = NULL; 352706f2543Smrg extraLen = 0; 353706f2543Smrg } 354706f2543Smrg else 355706f2543Smrg { 356706f2543Smrg RRModePtr *modes; 357706f2543Smrg int num_modes; 358706f2543Smrg 359706f2543Smrg modes = RRModesForScreen (pScreen, &num_modes); 360706f2543Smrg if (!modes) 361706f2543Smrg return BadAlloc; 362706f2543Smrg 363706f2543Smrg rep.type = X_Reply; 364706f2543Smrg rep.sequenceNumber = client->sequence; 365706f2543Smrg rep.length = 0; 366706f2543Smrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 367706f2543Smrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 368706f2543Smrg rep.nCrtcs = pScrPriv->numCrtcs; 369706f2543Smrg rep.nOutputs = pScrPriv->numOutputs; 370706f2543Smrg rep.nModes = num_modes; 371706f2543Smrg rep.nbytesNames = 0; 372706f2543Smrg 373706f2543Smrg for (i = 0; i < num_modes; i++) 374706f2543Smrg rep.nbytesNames += modes[i]->mode.nameLength; 375706f2543Smrg 376706f2543Smrg rep.length = (pScrPriv->numCrtcs + 377706f2543Smrg pScrPriv->numOutputs + 378706f2543Smrg num_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) + 379706f2543Smrg bytes_to_int32(rep.nbytesNames)); 380706f2543Smrg 381706f2543Smrg extraLen = rep.length << 2; 382706f2543Smrg if (extraLen) 383706f2543Smrg { 384706f2543Smrg extra = malloc(extraLen); 385706f2543Smrg if (!extra) 386706f2543Smrg { 387706f2543Smrg free(modes); 388706f2543Smrg return BadAlloc; 389706f2543Smrg } 390706f2543Smrg } 391706f2543Smrg else 392706f2543Smrg extra = NULL; 393706f2543Smrg 394706f2543Smrg crtcs = (RRCrtc *) extra; 395706f2543Smrg outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs); 396706f2543Smrg modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs); 397706f2543Smrg names = (CARD8 *) (modeinfos + num_modes); 398706f2543Smrg 399706f2543Smrg if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) 400706f2543Smrg { 401706f2543Smrg has_primary = 1; 402706f2543Smrg crtcs[0] = pScrPriv->primaryOutput->crtc->id; 403706f2543Smrg if (client->swapped) 404706f2543Smrg swapl (&crtcs[0], n); 405706f2543Smrg } 406706f2543Smrg 407706f2543Smrg for (i = 0; i < pScrPriv->numCrtcs; i++) 408706f2543Smrg { 409706f2543Smrg if (has_primary && 410706f2543Smrg pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) 411706f2543Smrg { 412706f2543Smrg has_primary = 0; 413706f2543Smrg continue; 414706f2543Smrg } 415706f2543Smrg crtcs[i + has_primary] = pScrPriv->crtcs[i]->id; 416706f2543Smrg if (client->swapped) 417706f2543Smrg swapl (&crtcs[i + has_primary], n); 418706f2543Smrg } 419706f2543Smrg 420706f2543Smrg for (i = 0; i < pScrPriv->numOutputs; i++) 421706f2543Smrg { 422706f2543Smrg outputs[i] = pScrPriv->outputs[i]->id; 423706f2543Smrg if (client->swapped) 424706f2543Smrg swapl (&outputs[i], n); 425706f2543Smrg } 426706f2543Smrg 427706f2543Smrg for (i = 0; i < num_modes; i++) 428706f2543Smrg { 429706f2543Smrg RRModePtr mode = modes[i]; 430706f2543Smrg modeinfos[i] = mode->mode; 431706f2543Smrg if (client->swapped) 432706f2543Smrg { 433706f2543Smrg swapl (&modeinfos[i].id, n); 434706f2543Smrg swaps (&modeinfos[i].width, n); 435706f2543Smrg swaps (&modeinfos[i].height, n); 436706f2543Smrg swapl (&modeinfos[i].dotClock, n); 437706f2543Smrg swaps (&modeinfos[i].hSyncStart, n); 438706f2543Smrg swaps (&modeinfos[i].hSyncEnd, n); 439706f2543Smrg swaps (&modeinfos[i].hTotal, n); 440706f2543Smrg swaps (&modeinfos[i].hSkew, n); 441706f2543Smrg swaps (&modeinfos[i].vSyncStart, n); 442706f2543Smrg swaps (&modeinfos[i].vSyncEnd, n); 443706f2543Smrg swaps (&modeinfos[i].vTotal, n); 444706f2543Smrg swaps (&modeinfos[i].nameLength, n); 445706f2543Smrg swapl (&modeinfos[i].modeFlags, n); 446706f2543Smrg } 447706f2543Smrg memcpy (names, mode->name, 448706f2543Smrg mode->mode.nameLength); 449706f2543Smrg names += mode->mode.nameLength; 450706f2543Smrg } 451706f2543Smrg free(modes); 452706f2543Smrg assert (bytes_to_int32((char *) names - (char *) extra) == rep.length); 453706f2543Smrg } 454706f2543Smrg 455706f2543Smrg if (client->swapped) { 456706f2543Smrg swaps(&rep.sequenceNumber, n); 457706f2543Smrg swapl(&rep.length, n); 458706f2543Smrg swapl(&rep.timestamp, n); 459706f2543Smrg swapl(&rep.configTimestamp, n); 460706f2543Smrg swaps(&rep.nCrtcs, n); 461706f2543Smrg swaps(&rep.nOutputs, n); 462706f2543Smrg swaps(&rep.nModes, n); 463706f2543Smrg swaps(&rep.nbytesNames, n); 464706f2543Smrg } 465706f2543Smrg WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep); 466706f2543Smrg if (extraLen) 467706f2543Smrg { 468706f2543Smrg WriteToClient (client, extraLen, (char *) extra); 469706f2543Smrg free(extra); 470706f2543Smrg } 471706f2543Smrg return Success; 472706f2543Smrg} 473706f2543Smrg 474706f2543Smrgint 475706f2543SmrgProcRRGetScreenResources (ClientPtr client) 476706f2543Smrg{ 477706f2543Smrg return rrGetScreenResources(client, TRUE); 478706f2543Smrg} 479706f2543Smrg 480706f2543Smrgint 481706f2543SmrgProcRRGetScreenResourcesCurrent (ClientPtr client) 482706f2543Smrg{ 483706f2543Smrg return rrGetScreenResources(client, FALSE); 484706f2543Smrg} 485706f2543Smrg 486706f2543Smrgtypedef struct _RR10Data { 487706f2543Smrg RRScreenSizePtr sizes; 488706f2543Smrg int nsize; 489706f2543Smrg int nrefresh; 490706f2543Smrg int size; 491706f2543Smrg CARD16 refresh; 492706f2543Smrg} RR10DataRec, *RR10DataPtr; 493706f2543Smrg 494706f2543Smrg/* 495706f2543Smrg * Convert 1.2 monitor data into 1.0 screen data 496706f2543Smrg */ 497706f2543Smrgstatic RR10DataPtr 498706f2543SmrgRR10GetData (ScreenPtr pScreen, RROutputPtr output) 499706f2543Smrg{ 500706f2543Smrg RR10DataPtr data; 501706f2543Smrg RRScreenSizePtr size; 502706f2543Smrg int nmode = output->numModes + output->numUserModes; 503706f2543Smrg int o, os, l, r; 504706f2543Smrg RRScreenRatePtr refresh; 505706f2543Smrg CARD16 vRefresh; 506706f2543Smrg RRModePtr mode; 507706f2543Smrg Bool *used; 508706f2543Smrg 509706f2543Smrg /* Make sure there is plenty of space for any combination */ 510706f2543Smrg data = malloc (sizeof (RR10DataRec) + 511706f2543Smrg sizeof (RRScreenSize) * nmode + 512706f2543Smrg sizeof (RRScreenRate) * nmode + 513706f2543Smrg sizeof (Bool) * nmode); 514706f2543Smrg if (!data) 515706f2543Smrg return NULL; 516706f2543Smrg size = (RRScreenSizePtr) (data + 1); 517706f2543Smrg refresh = (RRScreenRatePtr) (size + nmode); 518706f2543Smrg used = (Bool *) (refresh + nmode); 519706f2543Smrg memset (used, '\0', sizeof (Bool) * nmode); 520706f2543Smrg data->sizes = size; 521706f2543Smrg data->nsize = 0; 522706f2543Smrg data->nrefresh = 0; 523706f2543Smrg data->size = 0; 524706f2543Smrg data->refresh = 0; 525706f2543Smrg 526706f2543Smrg /* 527706f2543Smrg * find modes not yet listed 528706f2543Smrg */ 529706f2543Smrg for (o = 0; o < output->numModes + output->numUserModes; o++) 530706f2543Smrg { 531706f2543Smrg if (used[o]) continue; 532706f2543Smrg 533706f2543Smrg if (o < output->numModes) 534706f2543Smrg mode = output->modes[o]; 535706f2543Smrg else 536706f2543Smrg mode = output->userModes[o - output->numModes]; 537706f2543Smrg 538706f2543Smrg l = data->nsize; 539706f2543Smrg size[l].id = data->nsize; 540706f2543Smrg size[l].width = mode->mode.width; 541706f2543Smrg size[l].height = mode->mode.height; 542706f2543Smrg if (output->mmWidth && output->mmHeight) { 543706f2543Smrg size[l].mmWidth = output->mmWidth; 544706f2543Smrg size[l].mmHeight = output->mmHeight; 545706f2543Smrg } else { 546706f2543Smrg size[l].mmWidth = pScreen->mmWidth; 547706f2543Smrg size[l].mmHeight = pScreen->mmHeight; 548706f2543Smrg } 549706f2543Smrg size[l].nRates = 0; 550706f2543Smrg size[l].pRates = &refresh[data->nrefresh]; 551706f2543Smrg data->nsize++; 552706f2543Smrg 553706f2543Smrg /* 554706f2543Smrg * Find all modes with matching size 555706f2543Smrg */ 556706f2543Smrg for (os = o; os < output->numModes + output->numUserModes; os++) 557706f2543Smrg { 558706f2543Smrg if (os < output->numModes) 559706f2543Smrg mode = output->modes[os]; 560706f2543Smrg else 561706f2543Smrg mode = output->userModes[os - output->numModes]; 562706f2543Smrg if (mode->mode.width == size[l].width && 563706f2543Smrg mode->mode.height == size[l].height) 564706f2543Smrg { 565706f2543Smrg vRefresh = RRVerticalRefresh (&mode->mode); 566706f2543Smrg used[os] = TRUE; 567706f2543Smrg 568706f2543Smrg for (r = 0; r < size[l].nRates; r++) 569706f2543Smrg if (vRefresh == size[l].pRates[r].rate) 570706f2543Smrg break; 571706f2543Smrg if (r == size[l].nRates) 572706f2543Smrg { 573706f2543Smrg size[l].pRates[r].rate = vRefresh; 574706f2543Smrg size[l].pRates[r].mode = mode; 575706f2543Smrg size[l].nRates++; 576706f2543Smrg data->nrefresh++; 577706f2543Smrg } 578706f2543Smrg if (mode == output->crtc->mode) 579706f2543Smrg { 580706f2543Smrg data->size = l; 581706f2543Smrg data->refresh = vRefresh; 582706f2543Smrg } 583706f2543Smrg } 584706f2543Smrg } 585706f2543Smrg } 586706f2543Smrg return data; 587706f2543Smrg} 588706f2543Smrg 589706f2543Smrgint 590706f2543SmrgProcRRGetScreenInfo (ClientPtr client) 591706f2543Smrg{ 592706f2543Smrg REQUEST(xRRGetScreenInfoReq); 593706f2543Smrg xRRGetScreenInfoReply rep; 594706f2543Smrg WindowPtr pWin; 595706f2543Smrg int n, rc; 596706f2543Smrg ScreenPtr pScreen; 597706f2543Smrg rrScrPrivPtr pScrPriv; 598706f2543Smrg CARD8 *extra; 599706f2543Smrg unsigned long extraLen; 600706f2543Smrg RROutputPtr output; 601706f2543Smrg 602706f2543Smrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 603706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 604706f2543Smrg if (rc != Success) 605706f2543Smrg return rc; 606706f2543Smrg 607706f2543Smrg pScreen = pWin->drawable.pScreen; 608706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 609706f2543Smrg rep.pad = 0; 610706f2543Smrg 611706f2543Smrg if (pScrPriv) 612706f2543Smrg if (!RRGetInfo (pScreen, TRUE)) 613706f2543Smrg return BadAlloc; 614706f2543Smrg 615706f2543Smrg output = RRFirstOutput (pScreen); 616706f2543Smrg 617706f2543Smrg if (!pScrPriv || !output) 618706f2543Smrg { 619706f2543Smrg rep.type = X_Reply; 620706f2543Smrg rep.setOfRotations = RR_Rotate_0; 621706f2543Smrg rep.sequenceNumber = client->sequence; 622706f2543Smrg rep.length = 0; 623706f2543Smrg rep.root = pWin->drawable.pScreen->root->drawable.id; 624706f2543Smrg rep.timestamp = currentTime.milliseconds; 625706f2543Smrg rep.configTimestamp = currentTime.milliseconds; 626706f2543Smrg rep.nSizes = 0; 627706f2543Smrg rep.sizeID = 0; 628706f2543Smrg rep.rotation = RR_Rotate_0; 629706f2543Smrg rep.rate = 0; 630706f2543Smrg rep.nrateEnts = 0; 631706f2543Smrg extra = 0; 632706f2543Smrg extraLen = 0; 633706f2543Smrg } 634706f2543Smrg else 635706f2543Smrg { 636706f2543Smrg int i, j; 637706f2543Smrg xScreenSizes *size; 638706f2543Smrg CARD16 *rates; 639706f2543Smrg CARD8 *data8; 640706f2543Smrg Bool has_rate = RRClientKnowsRates (client); 641706f2543Smrg RR10DataPtr pData; 642706f2543Smrg RRScreenSizePtr pSize; 643706f2543Smrg 644706f2543Smrg pData = RR10GetData (pScreen, output); 645706f2543Smrg if (!pData) 646706f2543Smrg return BadAlloc; 647706f2543Smrg 648706f2543Smrg rep.type = X_Reply; 649706f2543Smrg rep.setOfRotations = output->crtc->rotations; 650706f2543Smrg rep.sequenceNumber = client->sequence; 651706f2543Smrg rep.length = 0; 652706f2543Smrg rep.root = pWin->drawable.pScreen->root->drawable.id; 653706f2543Smrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 654706f2543Smrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 655706f2543Smrg rep.rotation = output->crtc->rotation; 656706f2543Smrg rep.nSizes = pData->nsize; 657706f2543Smrg rep.nrateEnts = pData->nrefresh + pData->nsize; 658706f2543Smrg rep.sizeID = pData->size; 659706f2543Smrg rep.rate = pData->refresh; 660706f2543Smrg 661706f2543Smrg extraLen = rep.nSizes * sizeof (xScreenSizes); 662706f2543Smrg if (has_rate) 663706f2543Smrg extraLen += rep.nrateEnts * sizeof (CARD16); 664706f2543Smrg 665706f2543Smrg if (extraLen) 666706f2543Smrg { 667706f2543Smrg extra = (CARD8 *) malloc(extraLen); 668706f2543Smrg if (!extra) 669706f2543Smrg { 670706f2543Smrg free(pData); 671706f2543Smrg return BadAlloc; 672706f2543Smrg } 673706f2543Smrg } 674706f2543Smrg else 675706f2543Smrg extra = NULL; 676706f2543Smrg 677706f2543Smrg /* 678706f2543Smrg * First comes the size information 679706f2543Smrg */ 680706f2543Smrg size = (xScreenSizes *) extra; 681706f2543Smrg rates = (CARD16 *) (size + rep.nSizes); 682706f2543Smrg for (i = 0; i < pData->nsize; i++) 683706f2543Smrg { 684706f2543Smrg pSize = &pData->sizes[i]; 685706f2543Smrg size->widthInPixels = pSize->width; 686706f2543Smrg size->heightInPixels = pSize->height; 687706f2543Smrg size->widthInMillimeters = pSize->mmWidth; 688706f2543Smrg size->heightInMillimeters = pSize->mmHeight; 689706f2543Smrg if (client->swapped) 690706f2543Smrg { 691706f2543Smrg swaps (&size->widthInPixels, n); 692706f2543Smrg swaps (&size->heightInPixels, n); 693706f2543Smrg swaps (&size->widthInMillimeters, n); 694706f2543Smrg swaps (&size->heightInMillimeters, n); 695706f2543Smrg } 696706f2543Smrg size++; 697706f2543Smrg if (has_rate) 698706f2543Smrg { 699706f2543Smrg *rates = pSize->nRates; 700706f2543Smrg if (client->swapped) 701706f2543Smrg { 702706f2543Smrg swaps (rates, n); 703706f2543Smrg } 704706f2543Smrg rates++; 705706f2543Smrg for (j = 0; j < pSize->nRates; j++) 706706f2543Smrg { 707706f2543Smrg *rates = pSize->pRates[j].rate; 708706f2543Smrg if (client->swapped) 709706f2543Smrg { 710706f2543Smrg swaps (rates, n); 711706f2543Smrg } 712706f2543Smrg rates++; 713706f2543Smrg } 714706f2543Smrg } 715706f2543Smrg } 716706f2543Smrg free(pData); 717706f2543Smrg 718706f2543Smrg data8 = (CARD8 *) rates; 719706f2543Smrg 720706f2543Smrg if (data8 - (CARD8 *) extra != extraLen) 721706f2543Smrg FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", 722706f2543Smrg (unsigned long)(data8 - (CARD8 *) extra), extraLen); 723706f2543Smrg rep.length = bytes_to_int32(extraLen); 724706f2543Smrg } 725706f2543Smrg if (client->swapped) { 726706f2543Smrg swaps(&rep.sequenceNumber, n); 727706f2543Smrg swapl(&rep.length, n); 728706f2543Smrg swapl(&rep.timestamp, n); 729706f2543Smrg swaps(&rep.rotation, n); 730706f2543Smrg swaps(&rep.nSizes, n); 731706f2543Smrg swaps(&rep.sizeID, n); 732706f2543Smrg swaps(&rep.rate, n); 733706f2543Smrg swaps(&rep.nrateEnts, n); 734706f2543Smrg } 735706f2543Smrg WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); 736706f2543Smrg if (extraLen) 737706f2543Smrg { 738706f2543Smrg WriteToClient (client, extraLen, (char *) extra); 739706f2543Smrg free(extra); 740706f2543Smrg } 741706f2543Smrg return Success; 742706f2543Smrg} 743706f2543Smrg 744706f2543Smrgint 745706f2543SmrgProcRRSetScreenConfig (ClientPtr client) 746706f2543Smrg{ 747706f2543Smrg REQUEST(xRRSetScreenConfigReq); 748706f2543Smrg xRRSetScreenConfigReply rep; 749706f2543Smrg DrawablePtr pDraw; 750706f2543Smrg int n, rc; 751706f2543Smrg ScreenPtr pScreen; 752706f2543Smrg rrScrPrivPtr pScrPriv; 753706f2543Smrg TimeStamp time; 754706f2543Smrg int i; 755706f2543Smrg Rotation rotation; 756706f2543Smrg int rate; 757706f2543Smrg Bool has_rate; 758706f2543Smrg RROutputPtr output; 759706f2543Smrg RRCrtcPtr crtc; 760706f2543Smrg RRModePtr mode; 761706f2543Smrg RR10DataPtr pData = NULL; 762706f2543Smrg RRScreenSizePtr pSize; 763706f2543Smrg int width, height; 764706f2543Smrg 765706f2543Smrg UpdateCurrentTime (); 766706f2543Smrg 767706f2543Smrg if (RRClientKnowsRates (client)) 768706f2543Smrg { 769706f2543Smrg REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); 770706f2543Smrg has_rate = TRUE; 771706f2543Smrg } 772706f2543Smrg else 773706f2543Smrg { 774706f2543Smrg REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); 775706f2543Smrg has_rate = FALSE; 776706f2543Smrg } 777706f2543Smrg 778706f2543Smrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); 779706f2543Smrg if (rc != Success) 780706f2543Smrg return rc; 781706f2543Smrg 782706f2543Smrg pScreen = pDraw->pScreen; 783706f2543Smrg 784706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 785706f2543Smrg 786706f2543Smrg time = ClientTimeToServerTime(stuff->timestamp); 787706f2543Smrg 788706f2543Smrg if (!pScrPriv) 789706f2543Smrg { 790706f2543Smrg time = currentTime; 791706f2543Smrg rep.status = RRSetConfigFailed; 792706f2543Smrg goto sendReply; 793706f2543Smrg } 794706f2543Smrg if (!RRGetInfo (pScreen, FALSE)) 795706f2543Smrg return BadAlloc; 796706f2543Smrg 797706f2543Smrg output = RRFirstOutput (pScreen); 798706f2543Smrg if (!output) 799706f2543Smrg { 800706f2543Smrg time = currentTime; 801706f2543Smrg rep.status = RRSetConfigFailed; 802706f2543Smrg goto sendReply; 803706f2543Smrg } 804706f2543Smrg 805706f2543Smrg crtc = output->crtc; 806706f2543Smrg 807706f2543Smrg /* 808706f2543Smrg * If the client's config timestamp is not the same as the last config 809706f2543Smrg * timestamp, then the config information isn't up-to-date and 810706f2543Smrg * can't even be validated. 811706f2543Smrg * 812706f2543Smrg * Note that the client only knows about the milliseconds part of the 813706f2543Smrg * timestamp, so using CompareTimeStamps here would cause randr to suddenly 814706f2543Smrg * stop working after several hours have passed (freedesktop bug #6502). 815706f2543Smrg */ 816706f2543Smrg if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) 817706f2543Smrg { 818706f2543Smrg rep.status = RRSetConfigInvalidConfigTime; 819706f2543Smrg goto sendReply; 820706f2543Smrg } 821706f2543Smrg 822706f2543Smrg pData = RR10GetData (pScreen, output); 823706f2543Smrg if (!pData) 824706f2543Smrg return BadAlloc; 825706f2543Smrg 826706f2543Smrg if (stuff->sizeID >= pData->nsize) 827706f2543Smrg { 828706f2543Smrg /* 829706f2543Smrg * Invalid size ID 830706f2543Smrg */ 831706f2543Smrg client->errorValue = stuff->sizeID; 832706f2543Smrg free(pData); 833706f2543Smrg return BadValue; 834706f2543Smrg } 835706f2543Smrg pSize = &pData->sizes[stuff->sizeID]; 836706f2543Smrg 837706f2543Smrg /* 838706f2543Smrg * Validate requested rotation 839706f2543Smrg */ 840706f2543Smrg rotation = (Rotation) stuff->rotation; 841706f2543Smrg 842706f2543Smrg /* test the rotation bits only! */ 843706f2543Smrg switch (rotation & 0xf) { 844706f2543Smrg case RR_Rotate_0: 845706f2543Smrg case RR_Rotate_90: 846706f2543Smrg case RR_Rotate_180: 847706f2543Smrg case RR_Rotate_270: 848706f2543Smrg break; 849706f2543Smrg default: 850706f2543Smrg /* 851706f2543Smrg * Invalid rotation 852706f2543Smrg */ 853706f2543Smrg client->errorValue = stuff->rotation; 854706f2543Smrg free(pData); 855706f2543Smrg return BadValue; 856706f2543Smrg } 857706f2543Smrg 858706f2543Smrg if ((~crtc->rotations) & rotation) 859706f2543Smrg { 860706f2543Smrg /* 861706f2543Smrg * requested rotation or reflection not supported by screen 862706f2543Smrg */ 863706f2543Smrg client->errorValue = stuff->rotation; 864706f2543Smrg free(pData); 865706f2543Smrg return BadMatch; 866706f2543Smrg } 867706f2543Smrg 868706f2543Smrg /* 869706f2543Smrg * Validate requested refresh 870706f2543Smrg */ 871706f2543Smrg if (has_rate) 872706f2543Smrg rate = (int) stuff->rate; 873706f2543Smrg else 874706f2543Smrg rate = 0; 875706f2543Smrg 876706f2543Smrg if (rate) 877706f2543Smrg { 878706f2543Smrg for (i = 0; i < pSize->nRates; i++) 879706f2543Smrg { 880706f2543Smrg if (pSize->pRates[i].rate == rate) 881706f2543Smrg break; 882706f2543Smrg } 883706f2543Smrg if (i == pSize->nRates) 884706f2543Smrg { 885706f2543Smrg /* 886706f2543Smrg * Invalid rate 887706f2543Smrg */ 888706f2543Smrg client->errorValue = rate; 889706f2543Smrg free(pData); 890706f2543Smrg return BadValue; 891706f2543Smrg } 892706f2543Smrg mode = pSize->pRates[i].mode; 893706f2543Smrg } 894706f2543Smrg else 895706f2543Smrg mode = pSize->pRates[0].mode; 896706f2543Smrg 897706f2543Smrg /* 898706f2543Smrg * Make sure the requested set-time is not older than 899706f2543Smrg * the last set-time 900706f2543Smrg */ 901706f2543Smrg if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) 902706f2543Smrg { 903706f2543Smrg rep.status = RRSetConfigInvalidTime; 904706f2543Smrg goto sendReply; 905706f2543Smrg } 906706f2543Smrg 907706f2543Smrg /* 908706f2543Smrg * If the screen size is changing, adjust all of the other outputs 909706f2543Smrg * to fit the new size, mirroring as much as possible 910706f2543Smrg */ 911706f2543Smrg width = mode->mode.width; 912706f2543Smrg height = mode->mode.height; 913706f2543Smrg if (width < pScrPriv->minWidth || pScrPriv->maxWidth < width) { 914706f2543Smrg client->errorValue = width; 915706f2543Smrg free(pData); 916706f2543Smrg return BadValue; 917706f2543Smrg } 918706f2543Smrg if (height < pScrPriv->minHeight || pScrPriv->maxHeight < height) { 919706f2543Smrg client->errorValue = height; 920706f2543Smrg free(pData); 921706f2543Smrg return BadValue; 922706f2543Smrg } 923706f2543Smrg 924706f2543Smrg if (rotation & (RR_Rotate_90|RR_Rotate_270)) 925706f2543Smrg { 926706f2543Smrg width = mode->mode.height; 927706f2543Smrg height = mode->mode.width; 928706f2543Smrg } 929706f2543Smrg 930706f2543Smrg if (width != pScreen->width || height != pScreen->height) 931706f2543Smrg { 932706f2543Smrg int c; 933706f2543Smrg 934706f2543Smrg for (c = 0; c < pScrPriv->numCrtcs; c++) 935706f2543Smrg { 936706f2543Smrg if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, 937706f2543Smrg 0, NULL)) 938706f2543Smrg { 939706f2543Smrg rep.status = RRSetConfigFailed; 940706f2543Smrg /* XXX recover from failure */ 941706f2543Smrg goto sendReply; 942706f2543Smrg } 943706f2543Smrg } 944706f2543Smrg if (!RRScreenSizeSet (pScreen, width, height, 945706f2543Smrg pScreen->mmWidth, pScreen->mmHeight)) 946706f2543Smrg { 947706f2543Smrg rep.status = RRSetConfigFailed; 948706f2543Smrg /* XXX recover from failure */ 949706f2543Smrg goto sendReply; 950706f2543Smrg } 951706f2543Smrg } 952706f2543Smrg 953706f2543Smrg if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output)) 954706f2543Smrg rep.status = RRSetConfigFailed; 955706f2543Smrg else { 956706f2543Smrg pScrPriv->lastSetTime = time; 957706f2543Smrg rep.status = RRSetConfigSuccess; 958706f2543Smrg } 959706f2543Smrg 960706f2543Smrg /* 961706f2543Smrg * XXX Configure other crtcs to mirror as much as possible 962706f2543Smrg */ 963706f2543Smrg 964706f2543SmrgsendReply: 965706f2543Smrg 966706f2543Smrg free(pData); 967706f2543Smrg 968706f2543Smrg rep.type = X_Reply; 969706f2543Smrg /* rep.status has already been filled in */ 970706f2543Smrg rep.length = 0; 971706f2543Smrg rep.sequenceNumber = client->sequence; 972706f2543Smrg 973706f2543Smrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 974706f2543Smrg rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; 975706f2543Smrg rep.root = pDraw->pScreen->root->drawable.id; 976706f2543Smrg 977706f2543Smrg if (client->swapped) 978706f2543Smrg { 979706f2543Smrg swaps(&rep.sequenceNumber, n); 980706f2543Smrg swapl(&rep.length, n); 981706f2543Smrg swapl(&rep.newTimestamp, n); 982706f2543Smrg swapl(&rep.newConfigTimestamp, n); 983706f2543Smrg swapl(&rep.root, n); 984706f2543Smrg } 985706f2543Smrg WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); 986706f2543Smrg 987706f2543Smrg return Success; 988706f2543Smrg} 989706f2543Smrg 990706f2543Smrgstatic CARD16 991706f2543SmrgRR10CurrentSizeID (ScreenPtr pScreen) 992706f2543Smrg{ 993706f2543Smrg CARD16 sizeID = 0xffff; 994706f2543Smrg RROutputPtr output = RRFirstOutput (pScreen); 995706f2543Smrg 996706f2543Smrg if (output) 997706f2543Smrg { 998706f2543Smrg RR10DataPtr data = RR10GetData (pScreen, output); 999706f2543Smrg if (data) 1000706f2543Smrg { 1001706f2543Smrg int i; 1002706f2543Smrg for (i = 0; i < data->nsize; i++) 1003706f2543Smrg if (data->sizes[i].width == pScreen->width && 1004706f2543Smrg data->sizes[i].height == pScreen->height) 1005706f2543Smrg { 1006706f2543Smrg sizeID = (CARD16) i; 1007706f2543Smrg break; 1008706f2543Smrg } 1009706f2543Smrg free(data); 1010706f2543Smrg } 1011706f2543Smrg } 1012706f2543Smrg return sizeID; 1013706f2543Smrg} 1014