1 /*
2  * Copyright © 2000 Compaq Computer Corporation
3  * Copyright © 2002 Hewlett-Packard Company
4  * Copyright © 2006 Intel Corporation
5  * Copyright © 2017 Keith Packard
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that copyright
10  * notice and this permission notice appear in supporting documentation, and
11  * that the name of the copyright holders not be used in advertising or
12  * publicity pertaining to distribution of the software without specific,
13  * written prior permission.  The copyright holders make no representations
14  * about the suitability of this software for any purpose.  It is provided "as
15  * is" without express or implied warranty.
16  *
17  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23  * OF THIS SOFTWARE.
24  *
25  * Author:  Jim Gettys, Hewlett-Packard Company, Inc.
26  *	    Keith Packard, Intel Corporation
27  */
28 
29 #ifdef HAVE_DIX_CONFIG_H
30 #include <dix-config.h>
31 #endif
32 
33 #include "randrstr.h"
34 #include "extinit.h"
35 
36 /* From render.h */
37 #ifndef SubPixelUnknown
38 #define SubPixelUnknown 0
39 #endif
40 
41 #define RR_VALIDATE
42 static int RRNScreens;
43 
44 #define wrap(priv,real,mem,func) {\
45     priv->mem = real->mem; \
46     real->mem = func; \
47 }
48 
49 #define unwrap(priv,real,mem) {\
50     real->mem = priv->mem; \
51 }
52 
53 static int ProcRRDispatch(ClientPtr pClient);
54 static int SProcRRDispatch(ClientPtr pClient);
55 
56 int RREventBase;
57 int RRErrorBase;
58 RESTYPE RRClientType, RREventType;      /* resource types for event masks */
59 DevPrivateKeyRec RRClientPrivateKeyRec;
60 
61 DevPrivateKeyRec rrPrivKeyRec;
62 
63 static void
RRClientCallback(CallbackListPtr * list,void * closure,void * data)64 RRClientCallback(CallbackListPtr *list, void *closure, void *data)
65 {
66     NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
67     ClientPtr pClient = clientinfo->client;
68 
69     rrClientPriv(pClient);
70     RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
71     int i;
72 
73     pRRClient->major_version = 0;
74     pRRClient->minor_version = 0;
75     for (i = 0; i < screenInfo.numScreens; i++) {
76         ScreenPtr pScreen = screenInfo.screens[i];
77 
78         rrScrPriv(pScreen);
79 
80         if (pScrPriv) {
81             pTimes[i].setTime = pScrPriv->lastSetTime;
82             pTimes[i].configTime = pScrPriv->lastConfigTime;
83         }
84     }
85 }
86 
87 static Bool
RRCloseScreen(ScreenPtr pScreen)88 RRCloseScreen(ScreenPtr pScreen)
89 {
90     rrScrPriv(pScreen);
91     int j;
92     RRLeasePtr lease, next;
93 
94     unwrap(pScrPriv, pScreen, CloseScreen);
95 
96     xorg_list_for_each_entry_safe(lease, next, &pScrPriv->leases, list)
97         RRTerminateLease(lease);
98     for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
99         RRCrtcDestroy(pScrPriv->crtcs[j]);
100     for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
101         RROutputDestroy(pScrPriv->outputs[j]);
102 
103     if (pScrPriv->provider)
104         RRProviderDestroy(pScrPriv->provider);
105 
106     RRMonitorClose(pScreen);
107 
108     free(pScrPriv->crtcs);
109     free(pScrPriv->outputs);
110     free(pScrPriv);
111     RRNScreens -= 1;            /* ok, one fewer screen with RandR running */
112     return (*pScreen->CloseScreen) (pScreen);
113 }
114 
115 static void
SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,xRRScreenChangeNotifyEvent * to)116 SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,
117                            xRRScreenChangeNotifyEvent * to)
118 {
119     to->type = from->type;
120     to->rotation = from->rotation;
121     cpswaps(from->sequenceNumber, to->sequenceNumber);
122     cpswapl(from->timestamp, to->timestamp);
123     cpswapl(from->configTimestamp, to->configTimestamp);
124     cpswapl(from->root, to->root);
125     cpswapl(from->window, to->window);
126     cpswaps(from->sizeID, to->sizeID);
127     cpswaps(from->subpixelOrder, to->subpixelOrder);
128     cpswaps(from->widthInPixels, to->widthInPixels);
129     cpswaps(from->heightInPixels, to->heightInPixels);
130     cpswaps(from->widthInMillimeters, to->widthInMillimeters);
131     cpswaps(from->heightInMillimeters, to->heightInMillimeters);
132 }
133 
134 static void
SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,xRRCrtcChangeNotifyEvent * to)135 SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,
136                          xRRCrtcChangeNotifyEvent * to)
137 {
138     to->type = from->type;
139     to->subCode = from->subCode;
140     cpswaps(from->sequenceNumber, to->sequenceNumber);
141     cpswapl(from->timestamp, to->timestamp);
142     cpswapl(from->window, to->window);
143     cpswapl(from->crtc, to->crtc);
144     cpswapl(from->mode, to->mode);
145     cpswaps(from->rotation, to->rotation);
146     /* pad1 */
147     cpswaps(from->x, to->x);
148     cpswaps(from->y, to->y);
149     cpswaps(from->width, to->width);
150     cpswaps(from->height, to->height);
151 }
152 
153 static void
SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,xRROutputChangeNotifyEvent * to)154 SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,
155                            xRROutputChangeNotifyEvent * to)
156 {
157     to->type = from->type;
158     to->subCode = from->subCode;
159     cpswaps(from->sequenceNumber, to->sequenceNumber);
160     cpswapl(from->timestamp, to->timestamp);
161     cpswapl(from->configTimestamp, to->configTimestamp);
162     cpswapl(from->window, to->window);
163     cpswapl(from->output, to->output);
164     cpswapl(from->crtc, to->crtc);
165     cpswapl(from->mode, to->mode);
166     cpswaps(from->rotation, to->rotation);
167     to->connection = from->connection;
168     to->subpixelOrder = from->subpixelOrder;
169 }
170 
171 static void
SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,xRROutputPropertyNotifyEvent * to)172 SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
173                              xRROutputPropertyNotifyEvent * to)
174 {
175     to->type = from->type;
176     to->subCode = from->subCode;
177     cpswaps(from->sequenceNumber, to->sequenceNumber);
178     cpswapl(from->window, to->window);
179     cpswapl(from->output, to->output);
180     cpswapl(from->atom, to->atom);
181     cpswapl(from->timestamp, to->timestamp);
182     to->state = from->state;
183     /* pad1 */
184     /* pad2 */
185     /* pad3 */
186     /* pad4 */
187 }
188 
189 static void
SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,xRRProviderChangeNotifyEvent * to)190 SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,
191                          xRRProviderChangeNotifyEvent * to)
192 {
193     to->type = from->type;
194     to->subCode = from->subCode;
195     cpswaps(from->sequenceNumber, to->sequenceNumber);
196     cpswapl(from->timestamp, to->timestamp);
197     cpswapl(from->window, to->window);
198     cpswapl(from->provider, to->provider);
199 }
200 
201 static void
SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,xRRProviderPropertyNotifyEvent * to)202 SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,
203                                xRRProviderPropertyNotifyEvent * to)
204 {
205     to->type = from->type;
206     to->subCode = from->subCode;
207     cpswaps(from->sequenceNumber, to->sequenceNumber);
208     cpswapl(from->window, to->window);
209     cpswapl(from->provider, to->provider);
210     cpswapl(from->atom, to->atom);
211     cpswapl(from->timestamp, to->timestamp);
212     to->state = from->state;
213     /* pad1 */
214     /* pad2 */
215     /* pad3 */
216     /* pad4 */
217 }
218 
219 static void _X_COLD
SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,xRRResourceChangeNotifyEvent * to)220 SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,
221                              xRRResourceChangeNotifyEvent * to)
222 {
223     to->type = from->type;
224     to->subCode = from->subCode;
225     cpswaps(from->sequenceNumber, to->sequenceNumber);
226     cpswapl(from->timestamp, to->timestamp);
227     cpswapl(from->window, to->window);
228 }
229 
230 static void _X_COLD
SRRLeaseNotifyEvent(xRRLeaseNotifyEvent * from,xRRLeaseNotifyEvent * to)231 SRRLeaseNotifyEvent(xRRLeaseNotifyEvent * from,
232                     xRRLeaseNotifyEvent * to)
233 {
234     to->type = from->type;
235     to->subCode = from->subCode;
236     cpswaps(from->sequenceNumber, to->sequenceNumber);
237     cpswapl(from->timestamp, to->timestamp);
238     cpswapl(from->window, to->window);
239     cpswapl(from->lease, to->lease);
240     to->created = from->created;
241 }
242 
243 static void _X_COLD
SRRNotifyEvent(xEvent * from,xEvent * to)244 SRRNotifyEvent(xEvent *from, xEvent *to)
245 {
246     switch (from->u.u.detail) {
247     case RRNotify_CrtcChange:
248         SRRCrtcChangeNotifyEvent((xRRCrtcChangeNotifyEvent *) from,
249                                  (xRRCrtcChangeNotifyEvent *) to);
250         break;
251     case RRNotify_OutputChange:
252         SRROutputChangeNotifyEvent((xRROutputChangeNotifyEvent *) from,
253                                    (xRROutputChangeNotifyEvent *) to);
254         break;
255     case RRNotify_OutputProperty:
256         SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from,
257                                      (xRROutputPropertyNotifyEvent *) to);
258         break;
259     case RRNotify_ProviderChange:
260         SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from,
261                                    (xRRProviderChangeNotifyEvent *) to);
262         break;
263     case RRNotify_ProviderProperty:
264         SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from,
265                                        (xRRProviderPropertyNotifyEvent *) to);
266         break;
267     case RRNotify_ResourceChange:
268         SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from,
269                                    (xRRResourceChangeNotifyEvent *) to);
270         break;
271     case RRNotify_Lease:
272         SRRLeaseNotifyEvent((xRRLeaseNotifyEvent *) from,
273                             (xRRLeaseNotifyEvent *) to);
274         break;
275     default:
276         break;
277     }
278 }
279 
280 static int RRGeneration;
281 
282 Bool
RRInit(void)283 RRInit(void)
284 {
285     if (RRGeneration != serverGeneration) {
286         if (!RRModeInit())
287             return FALSE;
288         if (!RRCrtcInit())
289             return FALSE;
290         if (!RROutputInit())
291             return FALSE;
292         if (!RRProviderInit())
293             return FALSE;
294         if (!RRLeaseInit())
295             return FALSE;
296         RRGeneration = serverGeneration;
297     }
298     if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
299         return FALSE;
300 
301     return TRUE;
302 }
303 
304 Bool
RRScreenInit(ScreenPtr pScreen)305 RRScreenInit(ScreenPtr pScreen)
306 {
307     rrScrPrivPtr pScrPriv;
308 
309     if (!RRInit())
310         return FALSE;
311 
312     pScrPriv = (rrScrPrivPtr) calloc(1, sizeof(rrScrPrivRec));
313     if (!pScrPriv)
314         return FALSE;
315 
316     SetRRScreen(pScreen, pScrPriv);
317 
318     /*
319      * Calling function best set these function vectors
320      */
321     pScrPriv->rrGetInfo = 0;
322     pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
323     pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
324 
325     pScrPriv->width = pScreen->width;
326     pScrPriv->height = pScreen->height;
327     pScrPriv->mmWidth = pScreen->mmWidth;
328     pScrPriv->mmHeight = pScreen->mmHeight;
329 #if RANDR_12_INTERFACE
330     pScrPriv->rrScreenSetSize = NULL;
331     pScrPriv->rrCrtcSet = NULL;
332     pScrPriv->rrCrtcSetGamma = NULL;
333 #endif
334 #if RANDR_10_INTERFACE
335     pScrPriv->rrSetConfig = 0;
336     pScrPriv->rotations = RR_Rotate_0;
337     pScrPriv->reqWidth = pScreen->width;
338     pScrPriv->reqHeight = pScreen->height;
339     pScrPriv->nSizes = 0;
340     pScrPriv->pSizes = NULL;
341     pScrPriv->rotation = RR_Rotate_0;
342     pScrPriv->rate = 0;
343     pScrPriv->size = 0;
344 #endif
345 
346     /*
347      * This value doesn't really matter -- any client must call
348      * GetScreenInfo before reading it which will automatically update
349      * the time
350      */
351     pScrPriv->lastSetTime = currentTime;
352     pScrPriv->lastConfigTime = currentTime;
353 
354     wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
355 
356     pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
357     pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
358     pScrPriv->numOutputs = 0;
359     pScrPriv->outputs = NULL;
360     pScrPriv->numCrtcs = 0;
361     pScrPriv->crtcs = NULL;
362 
363     xorg_list_init(&pScrPriv->leases);
364 
365     RRMonitorInit(pScreen);
366 
367     RRNScreens += 1;            /* keep count of screens that implement randr */
368     return TRUE;
369 }
370 
371  /*ARGSUSED*/ static int
RRFreeClient(void * data,XID id)372 RRFreeClient(void *data, XID id)
373 {
374     RREventPtr pRREvent;
375     WindowPtr pWin;
376     RREventPtr *pHead, pCur, pPrev;
377 
378     pRREvent = (RREventPtr) data;
379     pWin = pRREvent->window;
380     dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
381                             RREventType, serverClient, DixDestroyAccess);
382     if (pHead) {
383         pPrev = 0;
384         for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next)
385             pPrev = pCur;
386         if (pCur) {
387             if (pPrev)
388                 pPrev->next = pRREvent->next;
389             else
390                 *pHead = pRREvent->next;
391         }
392     }
393     free((void *) pRREvent);
394     return 1;
395 }
396 
397  /*ARGSUSED*/ static int
RRFreeEvents(void * data,XID id)398 RRFreeEvents(void *data, XID id)
399 {
400     RREventPtr *pHead, pCur, pNext;
401 
402     pHead = (RREventPtr *) data;
403     for (pCur = *pHead; pCur; pCur = pNext) {
404         pNext = pCur->next;
405         FreeResource(pCur->clientResource, RRClientType);
406         free((void *) pCur);
407     }
408     free((void *) pHead);
409     return 1;
410 }
411 
412 void
RRExtensionInit(void)413 RRExtensionInit(void)
414 {
415     ExtensionEntry *extEntry;
416 
417     if (RRNScreens == 0)
418         return;
419 
420     if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
421                                sizeof(RRClientRec) +
422                                screenInfo.numScreens * sizeof(RRTimesRec)))
423         return;
424     if (!AddCallback(&ClientStateCallback, RRClientCallback, 0))
425         return;
426 
427     RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
428     if (!RRClientType)
429         return;
430     RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
431     if (!RREventType)
432         return;
433     extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors,
434                             ProcRRDispatch, SProcRRDispatch,
435                             NULL, StandardMinorOpcode);
436     if (!extEntry)
437         return;
438     RRErrorBase = extEntry->errorBase;
439     RREventBase = extEntry->eventBase;
440     EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
441         SRRScreenChangeNotifyEvent;
442     EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
443         SRRNotifyEvent;
444 
445     RRModeInitErrorValue();
446     RRCrtcInitErrorValue();
447     RROutputInitErrorValue();
448     RRProviderInitErrorValue();
449 #ifdef PANORAMIX
450     RRXineramaExtensionInit();
451 #endif
452 }
453 
454 void
RRResourcesChanged(ScreenPtr pScreen)455 RRResourcesChanged(ScreenPtr pScreen)
456 {
457     rrScrPriv(pScreen);
458     pScrPriv->resourcesChanged = TRUE;
459 
460     RRSetChanged(pScreen);
461 }
462 
463 static void
RRDeliverResourceEvent(ClientPtr client,WindowPtr pWin)464 RRDeliverResourceEvent(ClientPtr client, WindowPtr pWin)
465 {
466     ScreenPtr pScreen = pWin->drawable.pScreen;
467 
468     rrScrPriv(pScreen);
469 
470     xRRResourceChangeNotifyEvent re = {
471         .type = RRNotify + RREventBase,
472         .subCode = RRNotify_ResourceChange,
473         .timestamp = pScrPriv->lastSetTime.milliseconds,
474         .window = pWin->drawable.id
475     };
476 
477     WriteEventsToClient(client, 1, (xEvent *) &re);
478 }
479 
480 static int
TellChanged(WindowPtr pWin,void * value)481 TellChanged(WindowPtr pWin, void *value)
482 {
483     RREventPtr *pHead, pRREvent;
484     ClientPtr client;
485     ScreenPtr pScreen = pWin->drawable.pScreen;
486     ScreenPtr iter;
487     rrScrPrivPtr pSlaveScrPriv;
488 
489     rrScrPriv(pScreen);
490     int i;
491 
492     dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
493                             RREventType, serverClient, DixReadAccess);
494     if (!pHead)
495         return WT_WALKCHILDREN;
496 
497     for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
498         client = pRREvent->client;
499         if (client == serverClient || client->clientGone)
500             continue;
501 
502         if (pRREvent->mask & RRScreenChangeNotifyMask)
503             RRDeliverScreenEvent(client, pWin, pScreen);
504 
505         if (pRREvent->mask & RRCrtcChangeNotifyMask) {
506             for (i = 0; i < pScrPriv->numCrtcs; i++) {
507                 RRCrtcPtr crtc = pScrPriv->crtcs[i];
508 
509                 if (crtc->changed)
510                     RRDeliverCrtcEvent(client, pWin, crtc);
511             }
512 
513             xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
514                 if (!iter->is_output_slave)
515                     continue;
516 
517                 pSlaveScrPriv = rrGetScrPriv(iter);
518                 for (i = 0; i < pSlaveScrPriv->numCrtcs; i++) {
519                     RRCrtcPtr crtc = pSlaveScrPriv->crtcs[i];
520 
521                     if (crtc->changed)
522                         RRDeliverCrtcEvent(client, pWin, crtc);
523                 }
524             }
525         }
526 
527         if (pRREvent->mask & RROutputChangeNotifyMask) {
528             for (i = 0; i < pScrPriv->numOutputs; i++) {
529                 RROutputPtr output = pScrPriv->outputs[i];
530 
531                 if (output->changed)
532                     RRDeliverOutputEvent(client, pWin, output);
533             }
534 
535             xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
536                 if (!iter->is_output_slave)
537                     continue;
538 
539                 pSlaveScrPriv = rrGetScrPriv(iter);
540                 for (i = 0; i < pSlaveScrPriv->numOutputs; i++) {
541                     RROutputPtr output = pSlaveScrPriv->outputs[i];
542 
543                     if (output->changed)
544                         RRDeliverOutputEvent(client, pWin, output);
545                 }
546             }
547         }
548 
549         if (pRREvent->mask & RRProviderChangeNotifyMask) {
550             xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
551                 pSlaveScrPriv = rrGetScrPriv(iter);
552                 if (pSlaveScrPriv->provider->changed)
553                     RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
554             }
555         }
556 
557         if (pRREvent->mask & RRResourceChangeNotifyMask) {
558             if (pScrPriv->resourcesChanged) {
559                 RRDeliverResourceEvent(client, pWin);
560             }
561         }
562 
563         if (pRREvent->mask & RRLeaseNotifyMask) {
564             if (pScrPriv->leasesChanged) {
565                 RRDeliverLeaseEvent(client, pWin);
566             }
567         }
568     }
569     return WT_WALKCHILDREN;
570 }
571 
572 void
RRSetChanged(ScreenPtr pScreen)573 RRSetChanged(ScreenPtr pScreen)
574 {
575     /* set changed bits on the master screen only */
576     ScreenPtr master;
577     rrScrPriv(pScreen);
578     rrScrPrivPtr mastersp;
579 
580     if (pScreen->isGPU) {
581         master = pScreen->current_master;
582         if (!master)
583             return;
584         mastersp = rrGetScrPriv(master);
585     }
586     else {
587         master = pScreen;
588         mastersp = pScrPriv;
589     }
590 
591     mastersp->changed = TRUE;
592 }
593 
594 /*
595  * Something changed; send events and adjust pointer position
596  */
597 void
RRTellChanged(ScreenPtr pScreen)598 RRTellChanged(ScreenPtr pScreen)
599 {
600     ScreenPtr master;
601     rrScrPriv(pScreen);
602     rrScrPrivPtr mastersp;
603     int i;
604     ScreenPtr iter;
605     rrScrPrivPtr pSlaveScrPriv;
606 
607     if (pScreen->isGPU) {
608         master = pScreen->current_master;
609         if (!master)
610             return;
611         mastersp = rrGetScrPriv(master);
612     }
613     else {
614         master = pScreen;
615         mastersp = pScrPriv;
616     }
617 
618     xorg_list_for_each_entry(iter, &master->slave_list, slave_head) {
619         pSlaveScrPriv = rrGetScrPriv(iter);
620 
621         if (!iter->is_output_slave)
622             continue;
623 
624         if (CompareTimeStamps(mastersp->lastSetTime,
625                               pSlaveScrPriv->lastSetTime) == EARLIER) {
626             mastersp->lastSetTime = pSlaveScrPriv->lastSetTime;
627         }
628     }
629 
630     if (mastersp->changed) {
631         UpdateCurrentTimeIf();
632         if (mastersp->configChanged) {
633             mastersp->lastConfigTime = currentTime;
634             mastersp->configChanged = FALSE;
635         }
636         pScrPriv->changed = FALSE;
637         mastersp->changed = FALSE;
638 
639         WalkTree(master, TellChanged, (void *) master);
640 
641         mastersp->resourcesChanged = FALSE;
642 
643         for (i = 0; i < pScrPriv->numOutputs; i++)
644             pScrPriv->outputs[i]->changed = FALSE;
645         for (i = 0; i < pScrPriv->numCrtcs; i++)
646             pScrPriv->crtcs[i]->changed = FALSE;
647 
648         xorg_list_for_each_entry(iter, &master->slave_list, slave_head) {
649             pSlaveScrPriv = rrGetScrPriv(iter);
650             pSlaveScrPriv->provider->changed = FALSE;
651             if (iter->is_output_slave) {
652                 for (i = 0; i < pSlaveScrPriv->numOutputs; i++)
653                     pSlaveScrPriv->outputs[i]->changed = FALSE;
654                 for (i = 0; i < pSlaveScrPriv->numCrtcs; i++)
655                     pSlaveScrPriv->crtcs[i]->changed = FALSE;
656             }
657         }
658 
659         if (mastersp->layoutChanged) {
660             pScrPriv->layoutChanged = FALSE;
661             RRPointerScreenConfigured(master);
662             RRSendConfigNotify(master);
663         }
664     }
665 }
666 
667 /*
668  * Return the first output which is connected to an active CRTC
669  * Used in emulating 1.0 behaviour
670  */
671 RROutputPtr
RRFirstOutput(ScreenPtr pScreen)672 RRFirstOutput(ScreenPtr pScreen)
673 {
674     rrScrPriv(pScreen);
675     RROutputPtr output;
676     int i, j;
677 
678     if (!pScrPriv)
679         return NULL;
680 
681     if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
682         return pScrPriv->primaryOutput;
683 
684     for (i = 0; i < pScrPriv->numCrtcs; i++) {
685         RRCrtcPtr crtc = pScrPriv->crtcs[i];
686 
687         for (j = 0; j < pScrPriv->numOutputs; j++) {
688             output = pScrPriv->outputs[j];
689             if (output->crtc == crtc)
690                 return output;
691         }
692     }
693     return NULL;
694 }
695 
696 RRCrtcPtr
RRFirstEnabledCrtc(ScreenPtr pScreen)697 RRFirstEnabledCrtc(ScreenPtr pScreen)
698 {
699     rrScrPriv(pScreen);
700     RROutputPtr output;
701     int i, j;
702 
703     if (!pScrPriv)
704         return NULL;
705 
706     if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc &&
707         pScrPriv->primaryOutput->pScreen == pScreen)
708         return pScrPriv->primaryOutput->crtc;
709 
710     for (i = 0; i < pScrPriv->numCrtcs; i++) {
711         RRCrtcPtr crtc = pScrPriv->crtcs[i];
712 
713         for (j = 0; j < pScrPriv->numOutputs; j++) {
714             output = pScrPriv->outputs[j];
715             if (output->crtc == crtc && crtc->mode)
716                 return crtc;
717         }
718     }
719     return NULL;
720 }
721 
722 
723 CARD16
RRVerticalRefresh(xRRModeInfo * mode)724 RRVerticalRefresh(xRRModeInfo * mode)
725 {
726     CARD32 refresh;
727     CARD32 dots = mode->hTotal * mode->vTotal;
728 
729     if (!dots)
730         return 0;
731     refresh = (mode->dotClock + dots / 2) / dots;
732     if (refresh > 0xffff)
733         refresh = 0xffff;
734     return (CARD16) refresh;
735 }
736 
737 static int
ProcRRDispatch(ClientPtr client)738 ProcRRDispatch(ClientPtr client)
739 {
740     REQUEST(xReq);
741     if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
742         return BadRequest;
743     UpdateCurrentTimeIf();
744     return (*ProcRandrVector[stuff->data]) (client);
745 }
746 
747 static int _X_COLD
SProcRRDispatch(ClientPtr client)748 SProcRRDispatch(ClientPtr client)
749 {
750     REQUEST(xReq);
751     if (stuff->data >= RRNumberRequests || !SProcRandrVector[stuff->data])
752         return BadRequest;
753     UpdateCurrentTimeIf();
754     return (*SProcRandrVector[stuff->data]) (client);
755 }
756