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