randr.c revision 706f2543
1706f2543Smrg/* 2706f2543Smrg * Copyright © 2000 Compaq Computer Corporation 3706f2543Smrg * Copyright © 2002 Hewlett-Packard Company 4706f2543Smrg * Copyright © 2006 Intel Corporation 5706f2543Smrg * 6706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 7706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 8706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 9706f2543Smrg * notice and this permission notice appear in supporting documentation, and 10706f2543Smrg * that the name of the copyright holders not be used in advertising or 11706f2543Smrg * publicity pertaining to distribution of the software without specific, 12706f2543Smrg * written prior permission. The copyright holders make no representations 13706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 14706f2543Smrg * is" without express or implied warranty. 15706f2543Smrg * 16706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 22706f2543Smrg * OF THIS SOFTWARE. 23706f2543Smrg * 24706f2543Smrg * Author: Jim Gettys, Hewlett-Packard Company, Inc. 25706f2543Smrg * Keith Packard, Intel Corporation 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 29706f2543Smrg#include <dix-config.h> 30706f2543Smrg#endif 31706f2543Smrg 32706f2543Smrg#include "randrstr.h" 33706f2543Smrg 34706f2543Smrg/* From render.h */ 35706f2543Smrg#ifndef SubPixelUnknown 36706f2543Smrg#define SubPixelUnknown 0 37706f2543Smrg#endif 38706f2543Smrg 39706f2543Smrg#define RR_VALIDATE 40706f2543Smrgstatic int RRNScreens; 41706f2543Smrg 42706f2543Smrg#define wrap(priv,real,mem,func) {\ 43706f2543Smrg priv->mem = real->mem; \ 44706f2543Smrg real->mem = func; \ 45706f2543Smrg} 46706f2543Smrg 47706f2543Smrg#define unwrap(priv,real,mem) {\ 48706f2543Smrg real->mem = priv->mem; \ 49706f2543Smrg} 50706f2543Smrg 51706f2543Smrgstatic int ProcRRDispatch (ClientPtr pClient); 52706f2543Smrgstatic int SProcRRDispatch (ClientPtr pClient); 53706f2543Smrg 54706f2543Smrgint RREventBase; 55706f2543Smrgint RRErrorBase; 56706f2543SmrgRESTYPE RRClientType, RREventType; /* resource types for event masks */ 57706f2543SmrgDevPrivateKeyRec RRClientPrivateKeyRec; 58706f2543Smrg 59706f2543SmrgDevPrivateKeyRec rrPrivKeyRec; 60706f2543Smrg 61706f2543Smrgstatic void 62706f2543SmrgRRClientCallback (CallbackListPtr *list, 63706f2543Smrg pointer closure, 64706f2543Smrg pointer data) 65706f2543Smrg{ 66706f2543Smrg NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; 67706f2543Smrg ClientPtr pClient = clientinfo->client; 68706f2543Smrg rrClientPriv(pClient); 69706f2543Smrg RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); 70706f2543Smrg int i; 71706f2543Smrg 72706f2543Smrg pRRClient->major_version = 0; 73706f2543Smrg pRRClient->minor_version = 0; 74706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 75706f2543Smrg { 76706f2543Smrg ScreenPtr pScreen = screenInfo.screens[i]; 77706f2543Smrg rrScrPriv(pScreen); 78706f2543Smrg 79706f2543Smrg if (pScrPriv) 80706f2543Smrg { 81706f2543Smrg pTimes[i].setTime = pScrPriv->lastSetTime; 82706f2543Smrg pTimes[i].configTime = pScrPriv->lastConfigTime; 83706f2543Smrg } 84706f2543Smrg } 85706f2543Smrg} 86706f2543Smrg 87706f2543Smrgstatic Bool 88706f2543SmrgRRCloseScreen (int i, ScreenPtr pScreen) 89706f2543Smrg{ 90706f2543Smrg rrScrPriv(pScreen); 91706f2543Smrg int j; 92706f2543Smrg 93706f2543Smrg unwrap (pScrPriv, pScreen, CloseScreen); 94706f2543Smrg for (j = pScrPriv->numCrtcs - 1; j >= 0; j--) 95706f2543Smrg RRCrtcDestroy (pScrPriv->crtcs[j]); 96706f2543Smrg for (j = pScrPriv->numOutputs - 1; j >= 0; j--) 97706f2543Smrg RROutputDestroy (pScrPriv->outputs[j]); 98706f2543Smrg 99706f2543Smrg free(pScrPriv->crtcs); 100706f2543Smrg free(pScrPriv->outputs); 101706f2543Smrg free(pScrPriv); 102706f2543Smrg RRNScreens -= 1; /* ok, one fewer screen with RandR running */ 103706f2543Smrg return (*pScreen->CloseScreen) (i, pScreen); 104706f2543Smrg} 105706f2543Smrg 106706f2543Smrgstatic void 107706f2543SmrgSRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, 108706f2543Smrg xRRScreenChangeNotifyEvent *to) 109706f2543Smrg{ 110706f2543Smrg to->type = from->type; 111706f2543Smrg to->rotation = from->rotation; 112706f2543Smrg cpswaps(from->sequenceNumber, to->sequenceNumber); 113706f2543Smrg cpswapl(from->timestamp, to->timestamp); 114706f2543Smrg cpswapl(from->configTimestamp, to->configTimestamp); 115706f2543Smrg cpswapl(from->root, to->root); 116706f2543Smrg cpswapl(from->window, to->window); 117706f2543Smrg cpswaps(from->sizeID, to->sizeID); 118706f2543Smrg cpswaps(from->subpixelOrder, to->subpixelOrder); 119706f2543Smrg cpswaps(from->widthInPixels, to->widthInPixels); 120706f2543Smrg cpswaps(from->heightInPixels, to->heightInPixels); 121706f2543Smrg cpswaps(from->widthInMillimeters, to->widthInMillimeters); 122706f2543Smrg cpswaps(from->heightInMillimeters, to->heightInMillimeters); 123706f2543Smrg} 124706f2543Smrg 125706f2543Smrgstatic void 126706f2543SmrgSRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from, 127706f2543Smrg xRRCrtcChangeNotifyEvent *to) 128706f2543Smrg{ 129706f2543Smrg to->type = from->type; 130706f2543Smrg to->subCode = from->subCode; 131706f2543Smrg cpswaps(from->sequenceNumber, to->sequenceNumber); 132706f2543Smrg cpswapl(from->timestamp, to->timestamp); 133706f2543Smrg cpswapl(from->window, to->window); 134706f2543Smrg cpswapl(from->crtc, to->crtc); 135706f2543Smrg cpswapl(from->mode, to->mode); 136706f2543Smrg cpswaps(from->rotation, to->rotation); 137706f2543Smrg /* pad1 */ 138706f2543Smrg cpswaps(from->x, to->x); 139706f2543Smrg cpswaps(from->y, to->y); 140706f2543Smrg cpswaps(from->width, to->width); 141706f2543Smrg cpswaps(from->height, to->height); 142706f2543Smrg} 143706f2543Smrg 144706f2543Smrgstatic void 145706f2543SmrgSRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from, 146706f2543Smrg xRROutputChangeNotifyEvent *to) 147706f2543Smrg{ 148706f2543Smrg to->type = from->type; 149706f2543Smrg to->subCode = from->subCode; 150706f2543Smrg cpswaps(from->sequenceNumber, to->sequenceNumber); 151706f2543Smrg cpswapl(from->timestamp, to->timestamp); 152706f2543Smrg cpswapl(from->configTimestamp, to->configTimestamp); 153706f2543Smrg cpswapl(from->window, to->window); 154706f2543Smrg cpswapl(from->output, to->output); 155706f2543Smrg cpswapl(from->crtc, to->crtc); 156706f2543Smrg cpswapl(from->mode, to->mode); 157706f2543Smrg cpswaps(from->rotation, to->rotation); 158706f2543Smrg to->connection = from->connection; 159706f2543Smrg to->subpixelOrder = from->subpixelOrder; 160706f2543Smrg} 161706f2543Smrg 162706f2543Smrgstatic void 163706f2543SmrgSRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from, 164706f2543Smrg xRROutputPropertyNotifyEvent *to) 165706f2543Smrg{ 166706f2543Smrg to->type = from->type; 167706f2543Smrg to->subCode = from->subCode; 168706f2543Smrg cpswaps(from->sequenceNumber, to->sequenceNumber); 169706f2543Smrg cpswapl(from->window, to->window); 170706f2543Smrg cpswapl(from->output, to->output); 171706f2543Smrg cpswapl(from->atom, to->atom); 172706f2543Smrg cpswapl(from->timestamp, to->timestamp); 173706f2543Smrg to->state = from->state; 174706f2543Smrg /* pad1 */ 175706f2543Smrg /* pad2 */ 176706f2543Smrg /* pad3 */ 177706f2543Smrg /* pad4 */ 178706f2543Smrg} 179706f2543Smrg 180706f2543Smrgstatic void 181706f2543SmrgSRRNotifyEvent (xEvent *from, 182706f2543Smrg xEvent *to) 183706f2543Smrg{ 184706f2543Smrg switch (from->u.u.detail) { 185706f2543Smrg case RRNotify_CrtcChange: 186706f2543Smrg SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from, 187706f2543Smrg (xRRCrtcChangeNotifyEvent *) to); 188706f2543Smrg break; 189706f2543Smrg case RRNotify_OutputChange: 190706f2543Smrg SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from, 191706f2543Smrg (xRROutputChangeNotifyEvent *) to); 192706f2543Smrg break; 193706f2543Smrg case RRNotify_OutputProperty: 194706f2543Smrg SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from, 195706f2543Smrg (xRROutputPropertyNotifyEvent *) to); 196706f2543Smrg break; 197706f2543Smrg default: 198706f2543Smrg break; 199706f2543Smrg } 200706f2543Smrg} 201706f2543Smrg 202706f2543Smrgstatic int RRGeneration; 203706f2543Smrg 204706f2543SmrgBool RRInit (void) 205706f2543Smrg{ 206706f2543Smrg if (RRGeneration != serverGeneration) 207706f2543Smrg { 208706f2543Smrg if (!RRModeInit ()) 209706f2543Smrg return FALSE; 210706f2543Smrg if (!RRCrtcInit ()) 211706f2543Smrg return FALSE; 212706f2543Smrg if (!RROutputInit ()) 213706f2543Smrg return FALSE; 214706f2543Smrg RRGeneration = serverGeneration; 215706f2543Smrg } 216706f2543Smrg if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0)) 217706f2543Smrg return FALSE; 218706f2543Smrg 219706f2543Smrg return TRUE; 220706f2543Smrg} 221706f2543Smrg 222706f2543SmrgBool RRScreenInit(ScreenPtr pScreen) 223706f2543Smrg{ 224706f2543Smrg rrScrPrivPtr pScrPriv; 225706f2543Smrg 226706f2543Smrg if (!RRInit ()) 227706f2543Smrg return FALSE; 228706f2543Smrg 229706f2543Smrg pScrPriv = (rrScrPrivPtr) calloc(1, sizeof (rrScrPrivRec)); 230706f2543Smrg if (!pScrPriv) 231706f2543Smrg return FALSE; 232706f2543Smrg 233706f2543Smrg SetRRScreen(pScreen, pScrPriv); 234706f2543Smrg 235706f2543Smrg /* 236706f2543Smrg * Calling function best set these function vectors 237706f2543Smrg */ 238706f2543Smrg pScrPriv->rrGetInfo = 0; 239706f2543Smrg pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width; 240706f2543Smrg pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height; 241706f2543Smrg 242706f2543Smrg pScrPriv->width = pScreen->width; 243706f2543Smrg pScrPriv->height = pScreen->height; 244706f2543Smrg pScrPriv->mmWidth = pScreen->mmWidth; 245706f2543Smrg pScrPriv->mmHeight = pScreen->mmHeight; 246706f2543Smrg#if RANDR_12_INTERFACE 247706f2543Smrg pScrPriv->rrScreenSetSize = NULL; 248706f2543Smrg pScrPriv->rrCrtcSet = NULL; 249706f2543Smrg pScrPriv->rrCrtcSetGamma = NULL; 250706f2543Smrg#endif 251706f2543Smrg#if RANDR_10_INTERFACE 252706f2543Smrg pScrPriv->rrSetConfig = 0; 253706f2543Smrg pScrPriv->rotations = RR_Rotate_0; 254706f2543Smrg pScrPriv->reqWidth = pScreen->width; 255706f2543Smrg pScrPriv->reqHeight = pScreen->height; 256706f2543Smrg pScrPriv->nSizes = 0; 257706f2543Smrg pScrPriv->pSizes = NULL; 258706f2543Smrg pScrPriv->rotation = RR_Rotate_0; 259706f2543Smrg pScrPriv->rate = 0; 260706f2543Smrg pScrPriv->size = 0; 261706f2543Smrg#endif 262706f2543Smrg 263706f2543Smrg /* 264706f2543Smrg * This value doesn't really matter -- any client must call 265706f2543Smrg * GetScreenInfo before reading it which will automatically update 266706f2543Smrg * the time 267706f2543Smrg */ 268706f2543Smrg pScrPriv->lastSetTime = currentTime; 269706f2543Smrg pScrPriv->lastConfigTime = currentTime; 270706f2543Smrg 271706f2543Smrg wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); 272706f2543Smrg 273706f2543Smrg pScrPriv->numOutputs = 0; 274706f2543Smrg pScrPriv->outputs = NULL; 275706f2543Smrg pScrPriv->numCrtcs = 0; 276706f2543Smrg pScrPriv->crtcs = NULL; 277706f2543Smrg 278706f2543Smrg RRNScreens += 1; /* keep count of screens that implement randr */ 279706f2543Smrg return TRUE; 280706f2543Smrg} 281706f2543Smrg 282706f2543Smrg/*ARGSUSED*/ 283706f2543Smrgstatic int 284706f2543SmrgRRFreeClient (pointer data, XID id) 285706f2543Smrg{ 286706f2543Smrg RREventPtr pRREvent; 287706f2543Smrg WindowPtr pWin; 288706f2543Smrg RREventPtr *pHead, pCur, pPrev; 289706f2543Smrg 290706f2543Smrg pRREvent = (RREventPtr) data; 291706f2543Smrg pWin = pRREvent->window; 292706f2543Smrg dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, 293706f2543Smrg RREventType, serverClient, DixDestroyAccess); 294706f2543Smrg if (pHead) { 295706f2543Smrg pPrev = 0; 296706f2543Smrg for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) 297706f2543Smrg pPrev = pCur; 298706f2543Smrg if (pCur) 299706f2543Smrg { 300706f2543Smrg if (pPrev) 301706f2543Smrg pPrev->next = pRREvent->next; 302706f2543Smrg else 303706f2543Smrg *pHead = pRREvent->next; 304706f2543Smrg } 305706f2543Smrg } 306706f2543Smrg free((pointer) pRREvent); 307706f2543Smrg return 1; 308706f2543Smrg} 309706f2543Smrg 310706f2543Smrg/*ARGSUSED*/ 311706f2543Smrgstatic int 312706f2543SmrgRRFreeEvents (pointer data, XID id) 313706f2543Smrg{ 314706f2543Smrg RREventPtr *pHead, pCur, pNext; 315706f2543Smrg 316706f2543Smrg pHead = (RREventPtr *) data; 317706f2543Smrg for (pCur = *pHead; pCur; pCur = pNext) { 318706f2543Smrg pNext = pCur->next; 319706f2543Smrg FreeResource (pCur->clientResource, RRClientType); 320706f2543Smrg free((pointer) pCur); 321706f2543Smrg } 322706f2543Smrg free((pointer) pHead); 323706f2543Smrg return 1; 324706f2543Smrg} 325706f2543Smrg 326706f2543Smrgvoid 327706f2543SmrgRRExtensionInit (void) 328706f2543Smrg{ 329706f2543Smrg ExtensionEntry *extEntry; 330706f2543Smrg 331706f2543Smrg if (RRNScreens == 0) return; 332706f2543Smrg 333706f2543Smrg if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT, 334706f2543Smrg sizeof (RRClientRec) + 335706f2543Smrg screenInfo.numScreens * sizeof (RRTimesRec))) 336706f2543Smrg return; 337706f2543Smrg if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) 338706f2543Smrg return; 339706f2543Smrg 340706f2543Smrg RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient"); 341706f2543Smrg if (!RRClientType) 342706f2543Smrg return; 343706f2543Smrg RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent"); 344706f2543Smrg if (!RREventType) 345706f2543Smrg return; 346706f2543Smrg extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, 347706f2543Smrg ProcRRDispatch, SProcRRDispatch, 348706f2543Smrg NULL, StandardMinorOpcode); 349706f2543Smrg if (!extEntry) 350706f2543Smrg return; 351706f2543Smrg RRErrorBase = extEntry->errorBase; 352706f2543Smrg RREventBase = extEntry->eventBase; 353706f2543Smrg EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) 354706f2543Smrg SRRScreenChangeNotifyEvent; 355706f2543Smrg EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr) 356706f2543Smrg SRRNotifyEvent; 357706f2543Smrg 358706f2543Smrg RRModeInitErrorValue(); 359706f2543Smrg RRCrtcInitErrorValue(); 360706f2543Smrg RROutputInitErrorValue(); 361706f2543Smrg 362706f2543Smrg#ifdef PANORAMIX 363706f2543Smrg RRXineramaExtensionInit(); 364706f2543Smrg#endif 365706f2543Smrg} 366706f2543Smrg 367706f2543Smrgstatic int 368706f2543SmrgTellChanged (WindowPtr pWin, pointer value) 369706f2543Smrg{ 370706f2543Smrg RREventPtr *pHead, pRREvent; 371706f2543Smrg ClientPtr client; 372706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 373706f2543Smrg rrScrPriv(pScreen); 374706f2543Smrg int i; 375706f2543Smrg 376706f2543Smrg dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, 377706f2543Smrg RREventType, serverClient, DixReadAccess); 378706f2543Smrg if (!pHead) 379706f2543Smrg return WT_WALKCHILDREN; 380706f2543Smrg 381706f2543Smrg for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) 382706f2543Smrg { 383706f2543Smrg client = pRREvent->client; 384706f2543Smrg if (client == serverClient || client->clientGone) 385706f2543Smrg continue; 386706f2543Smrg 387706f2543Smrg if (pRREvent->mask & RRScreenChangeNotifyMask) 388706f2543Smrg RRDeliverScreenEvent (client, pWin, pScreen); 389706f2543Smrg 390706f2543Smrg if (pRREvent->mask & RRCrtcChangeNotifyMask) 391706f2543Smrg { 392706f2543Smrg for (i = 0; i < pScrPriv->numCrtcs; i++) 393706f2543Smrg { 394706f2543Smrg RRCrtcPtr crtc = pScrPriv->crtcs[i]; 395706f2543Smrg if (crtc->changed) 396706f2543Smrg RRDeliverCrtcEvent (client, pWin, crtc); 397706f2543Smrg } 398706f2543Smrg } 399706f2543Smrg 400706f2543Smrg if (pRREvent->mask & RROutputChangeNotifyMask) 401706f2543Smrg { 402706f2543Smrg for (i = 0; i < pScrPriv->numOutputs; i++) 403706f2543Smrg { 404706f2543Smrg RROutputPtr output = pScrPriv->outputs[i]; 405706f2543Smrg if (output->changed) 406706f2543Smrg RRDeliverOutputEvent (client, pWin, output); 407706f2543Smrg } 408706f2543Smrg } 409706f2543Smrg } 410706f2543Smrg return WT_WALKCHILDREN; 411706f2543Smrg} 412706f2543Smrg 413706f2543Smrg/* 414706f2543Smrg * Something changed; send events and adjust pointer position 415706f2543Smrg */ 416706f2543Smrgvoid 417706f2543SmrgRRTellChanged (ScreenPtr pScreen) 418706f2543Smrg{ 419706f2543Smrg rrScrPriv (pScreen); 420706f2543Smrg int i; 421706f2543Smrg 422706f2543Smrg if (pScrPriv->changed) 423706f2543Smrg { 424706f2543Smrg UpdateCurrentTime (); 425706f2543Smrg if (pScrPriv->configChanged) 426706f2543Smrg { 427706f2543Smrg pScrPriv->lastConfigTime = currentTime; 428706f2543Smrg pScrPriv->configChanged = FALSE; 429706f2543Smrg } 430706f2543Smrg pScrPriv->changed = FALSE; 431706f2543Smrg WalkTree (pScreen, TellChanged, (pointer) pScreen); 432706f2543Smrg for (i = 0; i < pScrPriv->numOutputs; i++) 433706f2543Smrg pScrPriv->outputs[i]->changed = FALSE; 434706f2543Smrg for (i = 0; i < pScrPriv->numCrtcs; i++) 435706f2543Smrg pScrPriv->crtcs[i]->changed = FALSE; 436706f2543Smrg if (pScrPriv->layoutChanged) 437706f2543Smrg { 438706f2543Smrg pScrPriv->layoutChanged = FALSE; 439706f2543Smrg RRPointerScreenConfigured (pScreen); 440706f2543Smrg RRSendConfigNotify (pScreen); 441706f2543Smrg } 442706f2543Smrg } 443706f2543Smrg} 444706f2543Smrg 445706f2543Smrgvoid 446706f2543SmrgRRSetChanged(ScreenPtr pScreen) 447706f2543Smrg{ 448706f2543Smrg rrScrPriv(pScreen); 449706f2543Smrg 450706f2543Smrg pScrPriv->changed = TRUE; 451706f2543Smrg} 452706f2543Smrg 453706f2543Smrg/* 454706f2543Smrg * Return the first output which is connected to an active CRTC 455706f2543Smrg * Used in emulating 1.0 behaviour 456706f2543Smrg */ 457706f2543SmrgRROutputPtr 458706f2543SmrgRRFirstOutput (ScreenPtr pScreen) 459706f2543Smrg{ 460706f2543Smrg rrScrPriv(pScreen); 461706f2543Smrg RROutputPtr output; 462706f2543Smrg int i, j; 463706f2543Smrg 464706f2543Smrg if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) 465706f2543Smrg return pScrPriv->primaryOutput; 466706f2543Smrg 467706f2543Smrg for (i = 0; i < pScrPriv->numCrtcs; i++) 468706f2543Smrg { 469706f2543Smrg RRCrtcPtr crtc = pScrPriv->crtcs[i]; 470706f2543Smrg for (j = 0; j < pScrPriv->numOutputs; j++) 471706f2543Smrg { 472706f2543Smrg output = pScrPriv->outputs[j]; 473706f2543Smrg if (output->crtc == crtc) 474706f2543Smrg return output; 475706f2543Smrg } 476706f2543Smrg } 477706f2543Smrg return NULL; 478706f2543Smrg} 479706f2543Smrg 480706f2543SmrgCARD16 481706f2543SmrgRRVerticalRefresh (xRRModeInfo *mode) 482706f2543Smrg{ 483706f2543Smrg CARD32 refresh; 484706f2543Smrg CARD32 dots = mode->hTotal * mode->vTotal; 485706f2543Smrg if (!dots) 486706f2543Smrg return 0; 487706f2543Smrg refresh = (mode->dotClock + dots/2) / dots; 488706f2543Smrg if (refresh > 0xffff) 489706f2543Smrg refresh = 0xffff; 490706f2543Smrg return (CARD16) refresh; 491706f2543Smrg} 492706f2543Smrg 493706f2543Smrgstatic int 494706f2543SmrgProcRRDispatch (ClientPtr client) 495706f2543Smrg{ 496706f2543Smrg REQUEST(xReq); 497706f2543Smrg if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) 498706f2543Smrg return BadRequest; 499706f2543Smrg return (*ProcRandrVector[stuff->data]) (client); 500706f2543Smrg} 501706f2543Smrg 502706f2543Smrgstatic int 503706f2543SmrgSProcRRDispatch (ClientPtr client) 504706f2543Smrg{ 505706f2543Smrg REQUEST(xReq); 506706f2543Smrg if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) 507706f2543Smrg return BadRequest; 508706f2543Smrg return (*SProcRandrVector[stuff->data]) (client); 509706f2543Smrg} 510706f2543Smrg 511