xref: /OK3568_Linux_fs/external/xserver/randr/rrscreen.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2006 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that copyright
7*4882a593Smuzhiyun  * notice and this permission notice appear in supporting documentation, and
8*4882a593Smuzhiyun  * that the name of the copyright holders not be used in advertising or
9*4882a593Smuzhiyun  * publicity pertaining to distribution of the software without specific,
10*4882a593Smuzhiyun  * written prior permission.  The copyright holders make no representations
11*4882a593Smuzhiyun  * about the suitability of this software for any purpose.  It is provided "as
12*4882a593Smuzhiyun  * is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20*4882a593Smuzhiyun  * OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "randrstr.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static CARD16
26*4882a593Smuzhiyun  RR10CurrentSizeID(ScreenPtr pScreen);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  * Edit connection information block so that new clients
30*4882a593Smuzhiyun  * see the current screen size on connect
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun static void
RREditConnectionInfo(ScreenPtr pScreen)33*4882a593Smuzhiyun RREditConnectionInfo(ScreenPtr pScreen)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun     xConnSetup *connSetup;
36*4882a593Smuzhiyun     char *vendor;
37*4882a593Smuzhiyun     xPixmapFormat *formats;
38*4882a593Smuzhiyun     xWindowRoot *root;
39*4882a593Smuzhiyun     xDepth *depth;
40*4882a593Smuzhiyun     xVisualType *visual;
41*4882a593Smuzhiyun     int screen = 0;
42*4882a593Smuzhiyun     int d;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun     if (ConnectionInfo == NULL)
45*4882a593Smuzhiyun         return;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun     connSetup = (xConnSetup *) ConnectionInfo;
48*4882a593Smuzhiyun     vendor = (char *) connSetup + sizeof(xConnSetup);
49*4882a593Smuzhiyun     formats = (xPixmapFormat *) ((char *) vendor +
50*4882a593Smuzhiyun                                  pad_to_int32(connSetup->nbytesVendor));
51*4882a593Smuzhiyun     root = (xWindowRoot *) ((char *) formats +
52*4882a593Smuzhiyun                             sizeof(xPixmapFormat) *
53*4882a593Smuzhiyun                             screenInfo.numPixmapFormats);
54*4882a593Smuzhiyun     while (screen != pScreen->myNum) {
55*4882a593Smuzhiyun         depth = (xDepth *) ((char *) root + sizeof(xWindowRoot));
56*4882a593Smuzhiyun         for (d = 0; d < root->nDepths; d++) {
57*4882a593Smuzhiyun             visual = (xVisualType *) ((char *) depth + sizeof(xDepth));
58*4882a593Smuzhiyun             depth = (xDepth *) ((char *) visual +
59*4882a593Smuzhiyun                                 depth->nVisuals * sizeof(xVisualType));
60*4882a593Smuzhiyun         }
61*4882a593Smuzhiyun         root = (xWindowRoot *) ((char *) depth);
62*4882a593Smuzhiyun         screen++;
63*4882a593Smuzhiyun     }
64*4882a593Smuzhiyun     root->pixWidth = pScreen->width;
65*4882a593Smuzhiyun     root->pixHeight = pScreen->height;
66*4882a593Smuzhiyun     root->mmWidth = pScreen->mmWidth;
67*4882a593Smuzhiyun     root->mmHeight = pScreen->mmHeight;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun void
RRSendConfigNotify(ScreenPtr pScreen)71*4882a593Smuzhiyun RRSendConfigNotify(ScreenPtr pScreen)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun     WindowPtr pWin = pScreen->root;
74*4882a593Smuzhiyun     xEvent event = {
75*4882a593Smuzhiyun         .u.configureNotify.window = pWin->drawable.id,
76*4882a593Smuzhiyun         .u.configureNotify.aboveSibling = None,
77*4882a593Smuzhiyun         .u.configureNotify.x = 0,
78*4882a593Smuzhiyun         .u.configureNotify.y = 0,
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun     /* XXX xinerama stuff ? */
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun         .u.configureNotify.width = pWin->drawable.width,
83*4882a593Smuzhiyun         .u.configureNotify.height = pWin->drawable.height,
84*4882a593Smuzhiyun         .u.configureNotify.borderWidth = wBorderWidth(pWin),
85*4882a593Smuzhiyun         .u.configureNotify.override = pWin->overrideRedirect
86*4882a593Smuzhiyun     };
87*4882a593Smuzhiyun     event.u.u.type = ConfigureNotify;
88*4882a593Smuzhiyun     DeliverEvents(pWin, &event, 1, NullWindow);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun void
RRDeliverScreenEvent(ClientPtr client,WindowPtr pWin,ScreenPtr pScreen)92*4882a593Smuzhiyun RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun     rrScrPriv(pScreen);
95*4882a593Smuzhiyun     RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
96*4882a593Smuzhiyun     WindowPtr pRoot = pScreen->root;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun     xRRScreenChangeNotifyEvent se = {
99*4882a593Smuzhiyun         .type = RRScreenChangeNotify + RREventBase,
100*4882a593Smuzhiyun         .rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0),
101*4882a593Smuzhiyun         .timestamp = pScrPriv->lastSetTime.milliseconds,
102*4882a593Smuzhiyun         .configTimestamp = pScrPriv->lastConfigTime.milliseconds,
103*4882a593Smuzhiyun         .root = pRoot->drawable.id,
104*4882a593Smuzhiyun         .window = pWin->drawable.id,
105*4882a593Smuzhiyun         .subpixelOrder = PictureGetSubpixelOrder(pScreen),
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun         .sizeID = RR10CurrentSizeID(pScreen)
108*4882a593Smuzhiyun     };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun     if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) {
111*4882a593Smuzhiyun         se.widthInPixels = pScreen->height;
112*4882a593Smuzhiyun         se.heightInPixels = pScreen->width;
113*4882a593Smuzhiyun         se.widthInMillimeters = pScreen->mmHeight;
114*4882a593Smuzhiyun         se.heightInMillimeters = pScreen->mmWidth;
115*4882a593Smuzhiyun     }
116*4882a593Smuzhiyun     else {
117*4882a593Smuzhiyun         se.widthInPixels = pScreen->width;
118*4882a593Smuzhiyun         se.heightInPixels = pScreen->height;
119*4882a593Smuzhiyun         se.widthInMillimeters = pScreen->mmWidth;
120*4882a593Smuzhiyun         se.heightInMillimeters = pScreen->mmHeight;
121*4882a593Smuzhiyun     }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun     WriteEventsToClient(client, 1, (xEvent *) &se);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /*
127*4882a593Smuzhiyun  * Notify the extension that the screen size has been changed.
128*4882a593Smuzhiyun  * The driver is responsible for calling this whenever it has changed
129*4882a593Smuzhiyun  * the size of the screen
130*4882a593Smuzhiyun  */
131*4882a593Smuzhiyun void
RRScreenSizeNotify(ScreenPtr pScreen)132*4882a593Smuzhiyun RRScreenSizeNotify(ScreenPtr pScreen)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun     rrScrPriv(pScreen);
135*4882a593Smuzhiyun     /*
136*4882a593Smuzhiyun      * Deliver ConfigureNotify events when root changes
137*4882a593Smuzhiyun      * pixel size
138*4882a593Smuzhiyun      */
139*4882a593Smuzhiyun     if (pScrPriv->width == pScreen->width &&
140*4882a593Smuzhiyun         pScrPriv->height == pScreen->height &&
141*4882a593Smuzhiyun         pScrPriv->mmWidth == pScreen->mmWidth &&
142*4882a593Smuzhiyun         pScrPriv->mmHeight == pScreen->mmHeight)
143*4882a593Smuzhiyun         return;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun     pScrPriv->width = pScreen->width;
146*4882a593Smuzhiyun     pScrPriv->height = pScreen->height;
147*4882a593Smuzhiyun     pScrPriv->mmWidth = pScreen->mmWidth;
148*4882a593Smuzhiyun     pScrPriv->mmHeight = pScreen->mmHeight;
149*4882a593Smuzhiyun     RRSetChanged(pScreen);
150*4882a593Smuzhiyun /*    pScrPriv->sizeChanged = TRUE; */
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun     RRTellChanged(pScreen);
153*4882a593Smuzhiyun     RRSendConfigNotify(pScreen);
154*4882a593Smuzhiyun     RREditConnectionInfo(pScreen);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun     RRPointerScreenConfigured(pScreen);
157*4882a593Smuzhiyun     /*
158*4882a593Smuzhiyun      * Fix pointer bounds and location
159*4882a593Smuzhiyun      */
160*4882a593Smuzhiyun     ScreenRestructured(pScreen);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun /*
164*4882a593Smuzhiyun  * Request that the screen be resized
165*4882a593Smuzhiyun  */
166*4882a593Smuzhiyun Bool
RRScreenSizeSet(ScreenPtr pScreen,CARD16 width,CARD16 height,CARD32 mmWidth,CARD32 mmHeight)167*4882a593Smuzhiyun RRScreenSizeSet(ScreenPtr pScreen,
168*4882a593Smuzhiyun                 CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun     rrScrPriv(pScreen);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun #if RANDR_12_INTERFACE
173*4882a593Smuzhiyun     if (pScrPriv->rrScreenSetSize) {
174*4882a593Smuzhiyun         return (*pScrPriv->rrScreenSetSize) (pScreen,
175*4882a593Smuzhiyun                                              width, height, mmWidth, mmHeight);
176*4882a593Smuzhiyun     }
177*4882a593Smuzhiyun #endif
178*4882a593Smuzhiyun #if RANDR_10_INTERFACE
179*4882a593Smuzhiyun     if (pScrPriv->rrSetConfig) {
180*4882a593Smuzhiyun         return TRUE;            /* can't set size separately */
181*4882a593Smuzhiyun     }
182*4882a593Smuzhiyun #endif
183*4882a593Smuzhiyun     return FALSE;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun /*
187*4882a593Smuzhiyun  * Retrieve valid screen size range
188*4882a593Smuzhiyun  */
189*4882a593Smuzhiyun int
ProcRRGetScreenSizeRange(ClientPtr client)190*4882a593Smuzhiyun ProcRRGetScreenSizeRange(ClientPtr client)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun     REQUEST(xRRGetScreenSizeRangeReq);
193*4882a593Smuzhiyun     xRRGetScreenSizeRangeReply rep;
194*4882a593Smuzhiyun     WindowPtr pWin;
195*4882a593Smuzhiyun     ScreenPtr pScreen;
196*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv;
197*4882a593Smuzhiyun     int rc;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq);
200*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
201*4882a593Smuzhiyun     if (rc != Success)
202*4882a593Smuzhiyun         return rc;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun     pScreen = pWin->drawable.pScreen;
205*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun     rep = (xRRGetScreenSizeRangeReply) {
208*4882a593Smuzhiyun         .type = X_Reply,
209*4882a593Smuzhiyun         .pad = 0,
210*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
211*4882a593Smuzhiyun         .length = 0
212*4882a593Smuzhiyun     };
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun     if (pScrPriv) {
215*4882a593Smuzhiyun         if (!RRGetInfo(pScreen, FALSE))
216*4882a593Smuzhiyun             return BadAlloc;
217*4882a593Smuzhiyun         rep.minWidth = pScrPriv->minWidth;
218*4882a593Smuzhiyun         rep.minHeight = pScrPriv->minHeight;
219*4882a593Smuzhiyun         rep.maxWidth = pScrPriv->maxWidth;
220*4882a593Smuzhiyun         rep.maxHeight = pScrPriv->maxHeight;
221*4882a593Smuzhiyun     }
222*4882a593Smuzhiyun     else {
223*4882a593Smuzhiyun         rep.maxWidth = rep.minWidth = pScreen->width;
224*4882a593Smuzhiyun         rep.maxHeight = rep.minHeight = pScreen->height;
225*4882a593Smuzhiyun     }
226*4882a593Smuzhiyun     if (client->swapped) {
227*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
228*4882a593Smuzhiyun         swapl(&rep.length);
229*4882a593Smuzhiyun         swaps(&rep.minWidth);
230*4882a593Smuzhiyun         swaps(&rep.minHeight);
231*4882a593Smuzhiyun         swaps(&rep.maxWidth);
232*4882a593Smuzhiyun         swaps(&rep.maxHeight);
233*4882a593Smuzhiyun     }
234*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), &rep);
235*4882a593Smuzhiyun     return Success;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun int
ProcRRSetScreenSize(ClientPtr client)239*4882a593Smuzhiyun ProcRRSetScreenSize(ClientPtr client)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun     REQUEST(xRRSetScreenSizeReq);
242*4882a593Smuzhiyun     WindowPtr pWin;
243*4882a593Smuzhiyun     ScreenPtr pScreen;
244*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv;
245*4882a593Smuzhiyun     int i, rc;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
248*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
249*4882a593Smuzhiyun     if (rc != Success)
250*4882a593Smuzhiyun         return rc;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun     pScreen = pWin->drawable.pScreen;
253*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
254*4882a593Smuzhiyun     if (!pScrPriv)
255*4882a593Smuzhiyun         return BadMatch;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun     if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) {
258*4882a593Smuzhiyun         client->errorValue = stuff->width;
259*4882a593Smuzhiyun         return BadValue;
260*4882a593Smuzhiyun     }
261*4882a593Smuzhiyun     if (stuff->height < pScrPriv->minHeight ||
262*4882a593Smuzhiyun         pScrPriv->maxHeight < stuff->height) {
263*4882a593Smuzhiyun         client->errorValue = stuff->height;
264*4882a593Smuzhiyun         return BadValue;
265*4882a593Smuzhiyun     }
266*4882a593Smuzhiyun     for (i = 0; i < pScrPriv->numCrtcs; i++) {
267*4882a593Smuzhiyun         RRCrtcPtr crtc = pScrPriv->crtcs[i];
268*4882a593Smuzhiyun         RRModePtr mode = crtc->mode;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun         if (!RRCrtcIsLeased(crtc) && mode) {
271*4882a593Smuzhiyun             int source_width = mode->mode.width;
272*4882a593Smuzhiyun             int source_height = mode->mode.height;
273*4882a593Smuzhiyun             Rotation rotation = crtc->rotation;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun             if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
276*4882a593Smuzhiyun                 source_width = mode->mode.height;
277*4882a593Smuzhiyun                 source_height = mode->mode.width;
278*4882a593Smuzhiyun             }
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun             if (crtc->x + source_width > stuff->width ||
281*4882a593Smuzhiyun                 crtc->y + source_height > stuff->height)
282*4882a593Smuzhiyun                 return BadMatch;
283*4882a593Smuzhiyun         }
284*4882a593Smuzhiyun     }
285*4882a593Smuzhiyun     if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) {
286*4882a593Smuzhiyun         client->errorValue = 0;
287*4882a593Smuzhiyun         return BadValue;
288*4882a593Smuzhiyun     }
289*4882a593Smuzhiyun     if (!RRScreenSizeSet(pScreen,
290*4882a593Smuzhiyun                          stuff->width, stuff->height,
291*4882a593Smuzhiyun                          stuff->widthInMillimeters,
292*4882a593Smuzhiyun                          stuff->heightInMillimeters)) {
293*4882a593Smuzhiyun         return BadMatch;
294*4882a593Smuzhiyun     }
295*4882a593Smuzhiyun     return Success;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun #define update_totals(gpuscreen, pScrPriv) do {       \
300*4882a593Smuzhiyun     total_crtcs += pScrPriv->numCrtcs;                \
301*4882a593Smuzhiyun     total_outputs += pScrPriv->numOutputs;            \
302*4882a593Smuzhiyun     modes = RRModesForScreen(gpuscreen, &num_modes);  \
303*4882a593Smuzhiyun     if (!modes)                                       \
304*4882a593Smuzhiyun         return BadAlloc;                              \
305*4882a593Smuzhiyun     for (j = 0; j < num_modes; j++)                   \
306*4882a593Smuzhiyun         total_name_len += modes[j]->mode.nameLength;  \
307*4882a593Smuzhiyun     total_modes += num_modes;                         \
308*4882a593Smuzhiyun     free(modes);                                      \
309*4882a593Smuzhiyun } while(0)
310*4882a593Smuzhiyun 
swap_modeinfos(xRRModeInfo * modeinfos,int i)311*4882a593Smuzhiyun static inline void swap_modeinfos(xRRModeInfo *modeinfos, int i)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun     swapl(&modeinfos[i].id);
314*4882a593Smuzhiyun     swaps(&modeinfos[i].width);
315*4882a593Smuzhiyun     swaps(&modeinfos[i].height);
316*4882a593Smuzhiyun     swapl(&modeinfos[i].dotClock);
317*4882a593Smuzhiyun     swaps(&modeinfos[i].hSyncStart);
318*4882a593Smuzhiyun     swaps(&modeinfos[i].hSyncEnd);
319*4882a593Smuzhiyun     swaps(&modeinfos[i].hTotal);
320*4882a593Smuzhiyun     swaps(&modeinfos[i].hSkew);
321*4882a593Smuzhiyun     swaps(&modeinfos[i].vSyncStart);
322*4882a593Smuzhiyun     swaps(&modeinfos[i].vSyncEnd);
323*4882a593Smuzhiyun     swaps(&modeinfos[i].vTotal);
324*4882a593Smuzhiyun     swaps(&modeinfos[i].nameLength);
325*4882a593Smuzhiyun     swapl(&modeinfos[i].modeFlags);
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun #define update_arrays(gpuscreen, pScrPriv, primary_crtc, has_primary) do {            \
329*4882a593Smuzhiyun     for (j = 0; j < pScrPriv->numCrtcs; j++) {             \
330*4882a593Smuzhiyun         if (has_primary && \
331*4882a593Smuzhiyun             primary_crtc == pScrPriv->crtcs[j]) { \
332*4882a593Smuzhiyun             has_primary = 0;   \
333*4882a593Smuzhiyun             continue; \
334*4882a593Smuzhiyun         }\
335*4882a593Smuzhiyun         crtcs[crtc_count] = pScrPriv->crtcs[j]->id;        \
336*4882a593Smuzhiyun         if (client->swapped)                               \
337*4882a593Smuzhiyun             swapl(&crtcs[crtc_count]);                     \
338*4882a593Smuzhiyun         crtc_count++;                                      \
339*4882a593Smuzhiyun     }                                                      \
340*4882a593Smuzhiyun     for (j = 0; j < pScrPriv->numOutputs; j++) {           \
341*4882a593Smuzhiyun         outputs[output_count] = pScrPriv->outputs[j]->id;  \
342*4882a593Smuzhiyun         if (client->swapped)                               \
343*4882a593Smuzhiyun             swapl(&outputs[output_count]);                 \
344*4882a593Smuzhiyun         output_count++;                                    \
345*4882a593Smuzhiyun     }                                                      \
346*4882a593Smuzhiyun     {                                                      \
347*4882a593Smuzhiyun         RRModePtr mode;                                    \
348*4882a593Smuzhiyun         modes = RRModesForScreen(gpuscreen, &num_modes);   \
349*4882a593Smuzhiyun         for (j = 0; j < num_modes; j++) {                  \
350*4882a593Smuzhiyun             mode = modes[j];                               \
351*4882a593Smuzhiyun             modeinfos[mode_count] = mode->mode;            \
352*4882a593Smuzhiyun             if (client->swapped) {                         \
353*4882a593Smuzhiyun                 swap_modeinfos(modeinfos, mode_count);     \
354*4882a593Smuzhiyun             }                                              \
355*4882a593Smuzhiyun             memcpy(names, mode->name, mode->mode.nameLength); \
356*4882a593Smuzhiyun             names += mode->mode.nameLength;                \
357*4882a593Smuzhiyun             mode_count++;                                  \
358*4882a593Smuzhiyun         }                                                  \
359*4882a593Smuzhiyun         free(modes);                                       \
360*4882a593Smuzhiyun     }                                                      \
361*4882a593Smuzhiyun     } while (0)
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun static int
rrGetMultiScreenResources(ClientPtr client,Bool query,ScreenPtr pScreen)364*4882a593Smuzhiyun rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun     int j;
367*4882a593Smuzhiyun     int total_crtcs, total_outputs, total_modes, total_name_len;
368*4882a593Smuzhiyun     int crtc_count, output_count, mode_count;
369*4882a593Smuzhiyun     ScreenPtr iter;
370*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv;
371*4882a593Smuzhiyun     int num_modes;
372*4882a593Smuzhiyun     RRModePtr *modes;
373*4882a593Smuzhiyun     xRRGetScreenResourcesReply rep;
374*4882a593Smuzhiyun     unsigned long extraLen;
375*4882a593Smuzhiyun     CARD8 *extra;
376*4882a593Smuzhiyun     RRCrtc *crtcs;
377*4882a593Smuzhiyun     RRCrtcPtr primary_crtc = NULL;
378*4882a593Smuzhiyun     RROutput *outputs;
379*4882a593Smuzhiyun     xRRModeInfo *modeinfos;
380*4882a593Smuzhiyun     CARD8 *names;
381*4882a593Smuzhiyun     int has_primary = 0;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun     /* we need to iterate all the GPU masters and all their output slaves */
384*4882a593Smuzhiyun     total_crtcs = 0;
385*4882a593Smuzhiyun     total_outputs = 0;
386*4882a593Smuzhiyun     total_modes = 0;
387*4882a593Smuzhiyun     total_name_len = 0;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     if (query && pScrPriv)
392*4882a593Smuzhiyun         if (!RRGetInfo(pScreen, query))
393*4882a593Smuzhiyun             return BadAlloc;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun     update_totals(pScreen, pScrPriv);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun     xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
398*4882a593Smuzhiyun         if (!iter->is_output_slave)
399*4882a593Smuzhiyun             continue;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun         pScrPriv = rrGetScrPriv(iter);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun         if (query)
404*4882a593Smuzhiyun           if (!RRGetInfo(iter, query))
405*4882a593Smuzhiyun             return BadAlloc;
406*4882a593Smuzhiyun         update_totals(iter, pScrPriv);
407*4882a593Smuzhiyun     }
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
410*4882a593Smuzhiyun     rep = (xRRGetScreenResourcesReply) {
411*4882a593Smuzhiyun         .type = X_Reply,
412*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
413*4882a593Smuzhiyun         .length = 0,
414*4882a593Smuzhiyun         .timestamp = pScrPriv->lastSetTime.milliseconds,
415*4882a593Smuzhiyun         .configTimestamp = pScrPriv->lastConfigTime.milliseconds,
416*4882a593Smuzhiyun         .nCrtcs = total_crtcs,
417*4882a593Smuzhiyun         .nOutputs = total_outputs,
418*4882a593Smuzhiyun         .nModes = total_modes,
419*4882a593Smuzhiyun         .nbytesNames = total_name_len
420*4882a593Smuzhiyun     };
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun     rep.length = (total_crtcs + total_outputs +
423*4882a593Smuzhiyun                   total_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) +
424*4882a593Smuzhiyun                   bytes_to_int32(total_name_len));
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun     extraLen = rep.length << 2;
427*4882a593Smuzhiyun     if (extraLen) {
428*4882a593Smuzhiyun         extra = malloc(extraLen);
429*4882a593Smuzhiyun         if (!extra) {
430*4882a593Smuzhiyun             return BadAlloc;
431*4882a593Smuzhiyun         }
432*4882a593Smuzhiyun     }
433*4882a593Smuzhiyun     else
434*4882a593Smuzhiyun         extra = NULL;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun     crtcs = (RRCrtc *)extra;
437*4882a593Smuzhiyun     outputs = (RROutput *)(crtcs + total_crtcs);
438*4882a593Smuzhiyun     modeinfos = (xRRModeInfo *)(outputs + total_outputs);
439*4882a593Smuzhiyun     names = (CARD8 *)(modeinfos + total_modes);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun     crtc_count = 0;
442*4882a593Smuzhiyun     output_count = 0;
443*4882a593Smuzhiyun     mode_count = 0;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
446*4882a593Smuzhiyun     if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
447*4882a593Smuzhiyun         has_primary = 1;
448*4882a593Smuzhiyun         primary_crtc = pScrPriv->primaryOutput->crtc;
449*4882a593Smuzhiyun         crtcs[0] = pScrPriv->primaryOutput->crtc->id;
450*4882a593Smuzhiyun         if (client->swapped)
451*4882a593Smuzhiyun             swapl(&crtcs[0]);
452*4882a593Smuzhiyun         crtc_count = 1;
453*4882a593Smuzhiyun     }
454*4882a593Smuzhiyun     update_arrays(pScreen, pScrPriv, primary_crtc, has_primary);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun     xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
457*4882a593Smuzhiyun         if (!iter->is_output_slave)
458*4882a593Smuzhiyun             continue;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun         pScrPriv = rrGetScrPriv(iter);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun         update_arrays(iter, pScrPriv, primary_crtc, has_primary);
463*4882a593Smuzhiyun     }
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun     assert(bytes_to_int32((char *) names - (char *) extra) == rep.length);
466*4882a593Smuzhiyun     if (client->swapped) {
467*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
468*4882a593Smuzhiyun         swapl(&rep.length);
469*4882a593Smuzhiyun         swapl(&rep.timestamp);
470*4882a593Smuzhiyun         swapl(&rep.configTimestamp);
471*4882a593Smuzhiyun         swaps(&rep.nCrtcs);
472*4882a593Smuzhiyun         swaps(&rep.nOutputs);
473*4882a593Smuzhiyun         swaps(&rep.nModes);
474*4882a593Smuzhiyun         swaps(&rep.nbytesNames);
475*4882a593Smuzhiyun     }
476*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRGetScreenResourcesReply), &rep);
477*4882a593Smuzhiyun     if (extraLen) {
478*4882a593Smuzhiyun         WriteToClient(client, extraLen, extra);
479*4882a593Smuzhiyun         free(extra);
480*4882a593Smuzhiyun     }
481*4882a593Smuzhiyun     return Success;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun static int
rrGetScreenResources(ClientPtr client,Bool query)485*4882a593Smuzhiyun rrGetScreenResources(ClientPtr client, Bool query)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun     REQUEST(xRRGetScreenResourcesReq);
488*4882a593Smuzhiyun     xRRGetScreenResourcesReply rep;
489*4882a593Smuzhiyun     WindowPtr pWin;
490*4882a593Smuzhiyun     ScreenPtr pScreen;
491*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv;
492*4882a593Smuzhiyun     CARD8 *extra;
493*4882a593Smuzhiyun     unsigned long extraLen;
494*4882a593Smuzhiyun     int i, rc, has_primary = 0;
495*4882a593Smuzhiyun     RRCrtc *crtcs;
496*4882a593Smuzhiyun     RROutput *outputs;
497*4882a593Smuzhiyun     xRRModeInfo *modeinfos;
498*4882a593Smuzhiyun     CARD8 *names;
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
501*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
502*4882a593Smuzhiyun     if (rc != Success)
503*4882a593Smuzhiyun         return rc;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun     pScreen = pWin->drawable.pScreen;
506*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun     if (query && pScrPriv)
509*4882a593Smuzhiyun         if (!RRGetInfo(pScreen, query))
510*4882a593Smuzhiyun             return BadAlloc;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun     if (pScreen->output_slaves)
513*4882a593Smuzhiyun         return rrGetMultiScreenResources(client, query, pScreen);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun     if (!pScrPriv) {
516*4882a593Smuzhiyun         rep = (xRRGetScreenResourcesReply) {
517*4882a593Smuzhiyun             .type = X_Reply,
518*4882a593Smuzhiyun             .sequenceNumber = client->sequence,
519*4882a593Smuzhiyun             .length = 0,
520*4882a593Smuzhiyun             .timestamp = currentTime.milliseconds,
521*4882a593Smuzhiyun             .configTimestamp = currentTime.milliseconds,
522*4882a593Smuzhiyun             .nCrtcs = 0,
523*4882a593Smuzhiyun             .nOutputs = 0,
524*4882a593Smuzhiyun             .nModes = 0,
525*4882a593Smuzhiyun             .nbytesNames = 0
526*4882a593Smuzhiyun         };
527*4882a593Smuzhiyun         extra = NULL;
528*4882a593Smuzhiyun         extraLen = 0;
529*4882a593Smuzhiyun     }
530*4882a593Smuzhiyun     else {
531*4882a593Smuzhiyun         RRModePtr *modes;
532*4882a593Smuzhiyun         int num_modes;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun         modes = RRModesForScreen(pScreen, &num_modes);
535*4882a593Smuzhiyun         if (!modes)
536*4882a593Smuzhiyun             return BadAlloc;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun         rep = (xRRGetScreenResourcesReply) {
539*4882a593Smuzhiyun             .type = X_Reply,
540*4882a593Smuzhiyun             .sequenceNumber = client->sequence,
541*4882a593Smuzhiyun             .length = 0,
542*4882a593Smuzhiyun             .timestamp = pScrPriv->lastSetTime.milliseconds,
543*4882a593Smuzhiyun             .configTimestamp = pScrPriv->lastConfigTime.milliseconds,
544*4882a593Smuzhiyun             .nCrtcs = pScrPriv->numCrtcs,
545*4882a593Smuzhiyun             .nOutputs = pScrPriv->numOutputs,
546*4882a593Smuzhiyun             .nModes = num_modes,
547*4882a593Smuzhiyun             .nbytesNames = 0
548*4882a593Smuzhiyun         };
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun         for (i = 0; i < num_modes; i++)
552*4882a593Smuzhiyun             rep.nbytesNames += modes[i]->mode.nameLength;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun         rep.length = (pScrPriv->numCrtcs +
555*4882a593Smuzhiyun                       pScrPriv->numOutputs +
556*4882a593Smuzhiyun                       num_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) +
557*4882a593Smuzhiyun                       bytes_to_int32(rep.nbytesNames));
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun         extraLen = rep.length << 2;
560*4882a593Smuzhiyun         if (extraLen) {
561*4882a593Smuzhiyun             extra = calloc(1, extraLen);
562*4882a593Smuzhiyun             if (!extra) {
563*4882a593Smuzhiyun                 free(modes);
564*4882a593Smuzhiyun                 return BadAlloc;
565*4882a593Smuzhiyun             }
566*4882a593Smuzhiyun         }
567*4882a593Smuzhiyun         else
568*4882a593Smuzhiyun             extra = NULL;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun         crtcs = (RRCrtc *) extra;
571*4882a593Smuzhiyun         outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
572*4882a593Smuzhiyun         modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
573*4882a593Smuzhiyun         names = (CARD8 *) (modeinfos + num_modes);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun         if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
576*4882a593Smuzhiyun             has_primary = 1;
577*4882a593Smuzhiyun             crtcs[0] = pScrPriv->primaryOutput->crtc->id;
578*4882a593Smuzhiyun             if (client->swapped)
579*4882a593Smuzhiyun                 swapl(&crtcs[0]);
580*4882a593Smuzhiyun         }
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun         for (i = 0; i < pScrPriv->numCrtcs; i++) {
583*4882a593Smuzhiyun             if (has_primary &&
584*4882a593Smuzhiyun                 pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) {
585*4882a593Smuzhiyun                 has_primary = 0;
586*4882a593Smuzhiyun                 continue;
587*4882a593Smuzhiyun             }
588*4882a593Smuzhiyun             crtcs[i + has_primary] = pScrPriv->crtcs[i]->id;
589*4882a593Smuzhiyun             if (client->swapped)
590*4882a593Smuzhiyun                 swapl(&crtcs[i + has_primary]);
591*4882a593Smuzhiyun         }
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun         for (i = 0; i < pScrPriv->numOutputs; i++) {
594*4882a593Smuzhiyun             outputs[i] = pScrPriv->outputs[i]->id;
595*4882a593Smuzhiyun             if (client->swapped)
596*4882a593Smuzhiyun                 swapl(&outputs[i]);
597*4882a593Smuzhiyun         }
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun         for (i = 0; i < num_modes; i++) {
600*4882a593Smuzhiyun             RRModePtr mode = modes[i];
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun             modeinfos[i] = mode->mode;
603*4882a593Smuzhiyun             if (client->swapped) {
604*4882a593Smuzhiyun                 swapl(&modeinfos[i].id);
605*4882a593Smuzhiyun                 swaps(&modeinfos[i].width);
606*4882a593Smuzhiyun                 swaps(&modeinfos[i].height);
607*4882a593Smuzhiyun                 swapl(&modeinfos[i].dotClock);
608*4882a593Smuzhiyun                 swaps(&modeinfos[i].hSyncStart);
609*4882a593Smuzhiyun                 swaps(&modeinfos[i].hSyncEnd);
610*4882a593Smuzhiyun                 swaps(&modeinfos[i].hTotal);
611*4882a593Smuzhiyun                 swaps(&modeinfos[i].hSkew);
612*4882a593Smuzhiyun                 swaps(&modeinfos[i].vSyncStart);
613*4882a593Smuzhiyun                 swaps(&modeinfos[i].vSyncEnd);
614*4882a593Smuzhiyun                 swaps(&modeinfos[i].vTotal);
615*4882a593Smuzhiyun                 swaps(&modeinfos[i].nameLength);
616*4882a593Smuzhiyun                 swapl(&modeinfos[i].modeFlags);
617*4882a593Smuzhiyun             }
618*4882a593Smuzhiyun             memcpy(names, mode->name, mode->mode.nameLength);
619*4882a593Smuzhiyun             names += mode->mode.nameLength;
620*4882a593Smuzhiyun         }
621*4882a593Smuzhiyun         free(modes);
622*4882a593Smuzhiyun         assert(bytes_to_int32((char *) names - (char *) extra) == rep.length);
623*4882a593Smuzhiyun     }
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun     if (client->swapped) {
626*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
627*4882a593Smuzhiyun         swapl(&rep.length);
628*4882a593Smuzhiyun         swapl(&rep.timestamp);
629*4882a593Smuzhiyun         swapl(&rep.configTimestamp);
630*4882a593Smuzhiyun         swaps(&rep.nCrtcs);
631*4882a593Smuzhiyun         swaps(&rep.nOutputs);
632*4882a593Smuzhiyun         swaps(&rep.nModes);
633*4882a593Smuzhiyun         swaps(&rep.nbytesNames);
634*4882a593Smuzhiyun     }
635*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *) &rep);
636*4882a593Smuzhiyun     if (extraLen) {
637*4882a593Smuzhiyun         WriteToClient(client, extraLen, (char *) extra);
638*4882a593Smuzhiyun         free(extra);
639*4882a593Smuzhiyun     }
640*4882a593Smuzhiyun     return Success;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun int
ProcRRGetScreenResources(ClientPtr client)644*4882a593Smuzhiyun ProcRRGetScreenResources(ClientPtr client)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun     return rrGetScreenResources(client, TRUE);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun int
ProcRRGetScreenResourcesCurrent(ClientPtr client)650*4882a593Smuzhiyun ProcRRGetScreenResourcesCurrent(ClientPtr client)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun     return rrGetScreenResources(client, FALSE);
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun typedef struct _RR10Data {
656*4882a593Smuzhiyun     RRScreenSizePtr sizes;
657*4882a593Smuzhiyun     int nsize;
658*4882a593Smuzhiyun     int nrefresh;
659*4882a593Smuzhiyun     int size;
660*4882a593Smuzhiyun     CARD16 refresh;
661*4882a593Smuzhiyun } RR10DataRec, *RR10DataPtr;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun /*
664*4882a593Smuzhiyun  * Convert 1.2 monitor data into 1.0 screen data
665*4882a593Smuzhiyun  */
666*4882a593Smuzhiyun static RR10DataPtr
RR10GetData(ScreenPtr pScreen,RROutputPtr output)667*4882a593Smuzhiyun RR10GetData(ScreenPtr pScreen, RROutputPtr output)
668*4882a593Smuzhiyun {
669*4882a593Smuzhiyun     RR10DataPtr data;
670*4882a593Smuzhiyun     RRScreenSizePtr size;
671*4882a593Smuzhiyun     int nmode = output->numModes + output->numUserModes;
672*4882a593Smuzhiyun     int o, os, l, r;
673*4882a593Smuzhiyun     RRScreenRatePtr refresh;
674*4882a593Smuzhiyun     CARD16 vRefresh;
675*4882a593Smuzhiyun     RRModePtr mode;
676*4882a593Smuzhiyun     Bool *used;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun     /* Make sure there is plenty of space for any combination */
679*4882a593Smuzhiyun     data = malloc(sizeof(RR10DataRec) +
680*4882a593Smuzhiyun                   sizeof(RRScreenSize) * nmode +
681*4882a593Smuzhiyun                   sizeof(RRScreenRate) * nmode + sizeof(Bool) * nmode);
682*4882a593Smuzhiyun     if (!data)
683*4882a593Smuzhiyun         return NULL;
684*4882a593Smuzhiyun     size = (RRScreenSizePtr) (data + 1);
685*4882a593Smuzhiyun     refresh = (RRScreenRatePtr) (size + nmode);
686*4882a593Smuzhiyun     used = (Bool *) (refresh + nmode);
687*4882a593Smuzhiyun     memset(used, '\0', sizeof(Bool) * nmode);
688*4882a593Smuzhiyun     data->sizes = size;
689*4882a593Smuzhiyun     data->nsize = 0;
690*4882a593Smuzhiyun     data->nrefresh = 0;
691*4882a593Smuzhiyun     data->size = 0;
692*4882a593Smuzhiyun     data->refresh = 0;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun     /*
695*4882a593Smuzhiyun      * find modes not yet listed
696*4882a593Smuzhiyun      */
697*4882a593Smuzhiyun     for (o = 0; o < output->numModes + output->numUserModes; o++) {
698*4882a593Smuzhiyun         if (used[o])
699*4882a593Smuzhiyun             continue;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun         if (o < output->numModes)
702*4882a593Smuzhiyun             mode = output->modes[o];
703*4882a593Smuzhiyun         else
704*4882a593Smuzhiyun             mode = output->userModes[o - output->numModes];
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun         l = data->nsize;
707*4882a593Smuzhiyun         size[l].id = data->nsize;
708*4882a593Smuzhiyun         size[l].width = mode->mode.width;
709*4882a593Smuzhiyun         size[l].height = mode->mode.height;
710*4882a593Smuzhiyun         if (output->mmWidth && output->mmHeight) {
711*4882a593Smuzhiyun             size[l].mmWidth = output->mmWidth;
712*4882a593Smuzhiyun             size[l].mmHeight = output->mmHeight;
713*4882a593Smuzhiyun         }
714*4882a593Smuzhiyun         else {
715*4882a593Smuzhiyun             size[l].mmWidth = pScreen->mmWidth;
716*4882a593Smuzhiyun             size[l].mmHeight = pScreen->mmHeight;
717*4882a593Smuzhiyun         }
718*4882a593Smuzhiyun         size[l].nRates = 0;
719*4882a593Smuzhiyun         size[l].pRates = &refresh[data->nrefresh];
720*4882a593Smuzhiyun         data->nsize++;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun         /*
723*4882a593Smuzhiyun          * Find all modes with matching size
724*4882a593Smuzhiyun          */
725*4882a593Smuzhiyun         for (os = o; os < output->numModes + output->numUserModes; os++) {
726*4882a593Smuzhiyun             if (os < output->numModes)
727*4882a593Smuzhiyun                 mode = output->modes[os];
728*4882a593Smuzhiyun             else
729*4882a593Smuzhiyun                 mode = output->userModes[os - output->numModes];
730*4882a593Smuzhiyun             if (mode->mode.width == size[l].width &&
731*4882a593Smuzhiyun                 mode->mode.height == size[l].height) {
732*4882a593Smuzhiyun                 vRefresh = RRVerticalRefresh(&mode->mode);
733*4882a593Smuzhiyun                 used[os] = TRUE;
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun                 for (r = 0; r < size[l].nRates; r++)
736*4882a593Smuzhiyun                     if (vRefresh == size[l].pRates[r].rate)
737*4882a593Smuzhiyun                         break;
738*4882a593Smuzhiyun                 if (r == size[l].nRates) {
739*4882a593Smuzhiyun                     size[l].pRates[r].rate = vRefresh;
740*4882a593Smuzhiyun                     size[l].pRates[r].mode = mode;
741*4882a593Smuzhiyun                     size[l].nRates++;
742*4882a593Smuzhiyun                     data->nrefresh++;
743*4882a593Smuzhiyun                 }
744*4882a593Smuzhiyun                 if (mode == output->crtc->mode) {
745*4882a593Smuzhiyun                     data->size = l;
746*4882a593Smuzhiyun                     data->refresh = vRefresh;
747*4882a593Smuzhiyun                 }
748*4882a593Smuzhiyun             }
749*4882a593Smuzhiyun         }
750*4882a593Smuzhiyun     }
751*4882a593Smuzhiyun     return data;
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun int
ProcRRGetScreenInfo(ClientPtr client)755*4882a593Smuzhiyun ProcRRGetScreenInfo(ClientPtr client)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun     REQUEST(xRRGetScreenInfoReq);
758*4882a593Smuzhiyun     xRRGetScreenInfoReply rep;
759*4882a593Smuzhiyun     WindowPtr pWin;
760*4882a593Smuzhiyun     int rc;
761*4882a593Smuzhiyun     ScreenPtr pScreen;
762*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv;
763*4882a593Smuzhiyun     CARD8 *extra;
764*4882a593Smuzhiyun     unsigned long extraLen;
765*4882a593Smuzhiyun     RROutputPtr output;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
768*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
769*4882a593Smuzhiyun     if (rc != Success)
770*4882a593Smuzhiyun         return rc;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun     pScreen = pWin->drawable.pScreen;
773*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun     if (pScrPriv)
776*4882a593Smuzhiyun         if (!RRGetInfo(pScreen, TRUE))
777*4882a593Smuzhiyun             return BadAlloc;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun     output = RRFirstOutput(pScreen);
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun     if (!pScrPriv || !output) {
782*4882a593Smuzhiyun         rep = (xRRGetScreenInfoReply) {
783*4882a593Smuzhiyun             .type = X_Reply,
784*4882a593Smuzhiyun             .setOfRotations = RR_Rotate_0,
785*4882a593Smuzhiyun             .sequenceNumber = client->sequence,
786*4882a593Smuzhiyun             .length = 0,
787*4882a593Smuzhiyun             .root = pWin->drawable.pScreen->root->drawable.id,
788*4882a593Smuzhiyun             .timestamp = currentTime.milliseconds,
789*4882a593Smuzhiyun             .configTimestamp = currentTime.milliseconds,
790*4882a593Smuzhiyun             .nSizes = 0,
791*4882a593Smuzhiyun             .sizeID = 0,
792*4882a593Smuzhiyun             .rotation = RR_Rotate_0,
793*4882a593Smuzhiyun             .rate = 0,
794*4882a593Smuzhiyun             .nrateEnts = 0
795*4882a593Smuzhiyun         };
796*4882a593Smuzhiyun         extra = 0;
797*4882a593Smuzhiyun         extraLen = 0;
798*4882a593Smuzhiyun     }
799*4882a593Smuzhiyun     else {
800*4882a593Smuzhiyun         int i, j;
801*4882a593Smuzhiyun         xScreenSizes *size;
802*4882a593Smuzhiyun         CARD16 *rates;
803*4882a593Smuzhiyun         CARD8 *data8;
804*4882a593Smuzhiyun         Bool has_rate = RRClientKnowsRates(client);
805*4882a593Smuzhiyun         RR10DataPtr pData;
806*4882a593Smuzhiyun         RRScreenSizePtr pSize;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun         pData = RR10GetData(pScreen, output);
809*4882a593Smuzhiyun         if (!pData)
810*4882a593Smuzhiyun             return BadAlloc;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun         rep = (xRRGetScreenInfoReply) {
813*4882a593Smuzhiyun             .type = X_Reply,
814*4882a593Smuzhiyun             .setOfRotations = output->crtc->rotations,
815*4882a593Smuzhiyun             .sequenceNumber = client->sequence,
816*4882a593Smuzhiyun             .length = 0,
817*4882a593Smuzhiyun             .root = pWin->drawable.pScreen->root->drawable.id,
818*4882a593Smuzhiyun             .timestamp = pScrPriv->lastSetTime.milliseconds,
819*4882a593Smuzhiyun             .configTimestamp = pScrPriv->lastConfigTime.milliseconds,
820*4882a593Smuzhiyun             .rotation = output->crtc->rotation,
821*4882a593Smuzhiyun             .nSizes = pData->nsize,
822*4882a593Smuzhiyun             .nrateEnts = pData->nrefresh + pData->nsize,
823*4882a593Smuzhiyun             .sizeID = pData->size,
824*4882a593Smuzhiyun             .rate = pData->refresh
825*4882a593Smuzhiyun         };
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun         extraLen = rep.nSizes * sizeof(xScreenSizes);
828*4882a593Smuzhiyun         if (has_rate)
829*4882a593Smuzhiyun             extraLen += rep.nrateEnts * sizeof(CARD16);
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun         if (extraLen) {
832*4882a593Smuzhiyun             extra = (CARD8 *) malloc(extraLen);
833*4882a593Smuzhiyun             if (!extra) {
834*4882a593Smuzhiyun                 free(pData);
835*4882a593Smuzhiyun                 return BadAlloc;
836*4882a593Smuzhiyun             }
837*4882a593Smuzhiyun         }
838*4882a593Smuzhiyun         else
839*4882a593Smuzhiyun             extra = NULL;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun         /*
842*4882a593Smuzhiyun          * First comes the size information
843*4882a593Smuzhiyun          */
844*4882a593Smuzhiyun         size = (xScreenSizes *) extra;
845*4882a593Smuzhiyun         rates = (CARD16 *) (size + rep.nSizes);
846*4882a593Smuzhiyun         for (i = 0; i < pData->nsize; i++) {
847*4882a593Smuzhiyun             pSize = &pData->sizes[i];
848*4882a593Smuzhiyun             size->widthInPixels = pSize->width;
849*4882a593Smuzhiyun             size->heightInPixels = pSize->height;
850*4882a593Smuzhiyun             size->widthInMillimeters = pSize->mmWidth;
851*4882a593Smuzhiyun             size->heightInMillimeters = pSize->mmHeight;
852*4882a593Smuzhiyun             if (client->swapped) {
853*4882a593Smuzhiyun                 swaps(&size->widthInPixels);
854*4882a593Smuzhiyun                 swaps(&size->heightInPixels);
855*4882a593Smuzhiyun                 swaps(&size->widthInMillimeters);
856*4882a593Smuzhiyun                 swaps(&size->heightInMillimeters);
857*4882a593Smuzhiyun             }
858*4882a593Smuzhiyun             size++;
859*4882a593Smuzhiyun             if (has_rate) {
860*4882a593Smuzhiyun                 *rates = pSize->nRates;
861*4882a593Smuzhiyun                 if (client->swapped) {
862*4882a593Smuzhiyun                     swaps(rates);
863*4882a593Smuzhiyun                 }
864*4882a593Smuzhiyun                 rates++;
865*4882a593Smuzhiyun                 for (j = 0; j < pSize->nRates; j++) {
866*4882a593Smuzhiyun                     *rates = pSize->pRates[j].rate;
867*4882a593Smuzhiyun                     if (client->swapped) {
868*4882a593Smuzhiyun                         swaps(rates);
869*4882a593Smuzhiyun                     }
870*4882a593Smuzhiyun                     rates++;
871*4882a593Smuzhiyun                 }
872*4882a593Smuzhiyun             }
873*4882a593Smuzhiyun         }
874*4882a593Smuzhiyun         free(pData);
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun         data8 = (CARD8 *) rates;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun         if (data8 - (CARD8 *) extra != extraLen)
879*4882a593Smuzhiyun             FatalError("RRGetScreenInfo bad extra len %ld != %ld\n",
880*4882a593Smuzhiyun                        (unsigned long) (data8 - (CARD8 *) extra), extraLen);
881*4882a593Smuzhiyun         rep.length = bytes_to_int32(extraLen);
882*4882a593Smuzhiyun     }
883*4882a593Smuzhiyun     if (client->swapped) {
884*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
885*4882a593Smuzhiyun         swapl(&rep.length);
886*4882a593Smuzhiyun         swapl(&rep.timestamp);
887*4882a593Smuzhiyun         swapl(&rep.configTimestamp);
888*4882a593Smuzhiyun         swaps(&rep.rotation);
889*4882a593Smuzhiyun         swaps(&rep.nSizes);
890*4882a593Smuzhiyun         swaps(&rep.sizeID);
891*4882a593Smuzhiyun         swaps(&rep.rate);
892*4882a593Smuzhiyun         swaps(&rep.nrateEnts);
893*4882a593Smuzhiyun     }
894*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRGetScreenInfoReply), &rep);
895*4882a593Smuzhiyun     if (extraLen) {
896*4882a593Smuzhiyun         WriteToClient(client, extraLen, extra);
897*4882a593Smuzhiyun         free(extra);
898*4882a593Smuzhiyun     }
899*4882a593Smuzhiyun     return Success;
900*4882a593Smuzhiyun }
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun int
ProcRRSetScreenConfig(ClientPtr client)903*4882a593Smuzhiyun ProcRRSetScreenConfig(ClientPtr client)
904*4882a593Smuzhiyun {
905*4882a593Smuzhiyun     REQUEST(xRRSetScreenConfigReq);
906*4882a593Smuzhiyun     xRRSetScreenConfigReply rep;
907*4882a593Smuzhiyun     DrawablePtr pDraw;
908*4882a593Smuzhiyun     int rc;
909*4882a593Smuzhiyun     ScreenPtr pScreen;
910*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv;
911*4882a593Smuzhiyun     TimeStamp time;
912*4882a593Smuzhiyun     int i;
913*4882a593Smuzhiyun     Rotation rotation;
914*4882a593Smuzhiyun     int rate;
915*4882a593Smuzhiyun     Bool has_rate;
916*4882a593Smuzhiyun     CARD8 status;
917*4882a593Smuzhiyun     RROutputPtr output;
918*4882a593Smuzhiyun     RRCrtcPtr crtc;
919*4882a593Smuzhiyun     RRModePtr mode;
920*4882a593Smuzhiyun     RR10DataPtr pData = NULL;
921*4882a593Smuzhiyun     RRScreenSizePtr pSize;
922*4882a593Smuzhiyun     int width, height;
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun     UpdateCurrentTime();
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun     if (RRClientKnowsRates(client)) {
927*4882a593Smuzhiyun         REQUEST_SIZE_MATCH(xRRSetScreenConfigReq);
928*4882a593Smuzhiyun         has_rate = TRUE;
929*4882a593Smuzhiyun     }
930*4882a593Smuzhiyun     else {
931*4882a593Smuzhiyun         REQUEST_SIZE_MATCH(xRR1_0SetScreenConfigReq);
932*4882a593Smuzhiyun         has_rate = FALSE;
933*4882a593Smuzhiyun     }
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess);
936*4882a593Smuzhiyun     if (rc != Success)
937*4882a593Smuzhiyun         return rc;
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun     pScreen = pDraw->pScreen;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun     pScrPriv = rrGetScrPriv(pScreen);
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun     time = ClientTimeToServerTime(stuff->timestamp);
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun     if (!pScrPriv) {
946*4882a593Smuzhiyun         time = currentTime;
947*4882a593Smuzhiyun         status = RRSetConfigFailed;
948*4882a593Smuzhiyun         goto sendReply;
949*4882a593Smuzhiyun     }
950*4882a593Smuzhiyun     if (!RRGetInfo(pScreen, FALSE))
951*4882a593Smuzhiyun         return BadAlloc;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun     output = RRFirstOutput(pScreen);
954*4882a593Smuzhiyun     if (!output) {
955*4882a593Smuzhiyun         time = currentTime;
956*4882a593Smuzhiyun         status = RRSetConfigFailed;
957*4882a593Smuzhiyun         goto sendReply;
958*4882a593Smuzhiyun     }
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun     crtc = output->crtc;
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun     /*
963*4882a593Smuzhiyun      * If the client's config timestamp is not the same as the last config
964*4882a593Smuzhiyun      * timestamp, then the config information isn't up-to-date and
965*4882a593Smuzhiyun      * can't even be validated.
966*4882a593Smuzhiyun      *
967*4882a593Smuzhiyun      * Note that the client only knows about the milliseconds part of the
968*4882a593Smuzhiyun      * timestamp, so using CompareTimeStamps here would cause randr to suddenly
969*4882a593Smuzhiyun      * stop working after several hours have passed (freedesktop bug #6502).
970*4882a593Smuzhiyun      */
971*4882a593Smuzhiyun     if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) {
972*4882a593Smuzhiyun         status = RRSetConfigInvalidConfigTime;
973*4882a593Smuzhiyun         goto sendReply;
974*4882a593Smuzhiyun     }
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun     pData = RR10GetData(pScreen, output);
977*4882a593Smuzhiyun     if (!pData)
978*4882a593Smuzhiyun         return BadAlloc;
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun     if (stuff->sizeID >= pData->nsize) {
981*4882a593Smuzhiyun         /*
982*4882a593Smuzhiyun          * Invalid size ID
983*4882a593Smuzhiyun          */
984*4882a593Smuzhiyun         client->errorValue = stuff->sizeID;
985*4882a593Smuzhiyun         free(pData);
986*4882a593Smuzhiyun         return BadValue;
987*4882a593Smuzhiyun     }
988*4882a593Smuzhiyun     pSize = &pData->sizes[stuff->sizeID];
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun     /*
991*4882a593Smuzhiyun      * Validate requested rotation
992*4882a593Smuzhiyun      */
993*4882a593Smuzhiyun     rotation = (Rotation) stuff->rotation;
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun     /* test the rotation bits only! */
996*4882a593Smuzhiyun     switch (rotation & 0xf) {
997*4882a593Smuzhiyun     case RR_Rotate_0:
998*4882a593Smuzhiyun     case RR_Rotate_90:
999*4882a593Smuzhiyun     case RR_Rotate_180:
1000*4882a593Smuzhiyun     case RR_Rotate_270:
1001*4882a593Smuzhiyun         break;
1002*4882a593Smuzhiyun     default:
1003*4882a593Smuzhiyun         /*
1004*4882a593Smuzhiyun          * Invalid rotation
1005*4882a593Smuzhiyun          */
1006*4882a593Smuzhiyun         client->errorValue = stuff->rotation;
1007*4882a593Smuzhiyun         free(pData);
1008*4882a593Smuzhiyun         return BadValue;
1009*4882a593Smuzhiyun     }
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun     if ((~crtc->rotations) & rotation) {
1012*4882a593Smuzhiyun         /*
1013*4882a593Smuzhiyun          * requested rotation or reflection not supported by screen
1014*4882a593Smuzhiyun          */
1015*4882a593Smuzhiyun         client->errorValue = stuff->rotation;
1016*4882a593Smuzhiyun         free(pData);
1017*4882a593Smuzhiyun         return BadMatch;
1018*4882a593Smuzhiyun     }
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun     /*
1021*4882a593Smuzhiyun      * Validate requested refresh
1022*4882a593Smuzhiyun      */
1023*4882a593Smuzhiyun     if (has_rate)
1024*4882a593Smuzhiyun         rate = (int) stuff->rate;
1025*4882a593Smuzhiyun     else
1026*4882a593Smuzhiyun         rate = 0;
1027*4882a593Smuzhiyun 
1028*4882a593Smuzhiyun     if (rate) {
1029*4882a593Smuzhiyun         for (i = 0; i < pSize->nRates; i++) {
1030*4882a593Smuzhiyun             if (pSize->pRates[i].rate == rate)
1031*4882a593Smuzhiyun                 break;
1032*4882a593Smuzhiyun         }
1033*4882a593Smuzhiyun         if (i == pSize->nRates) {
1034*4882a593Smuzhiyun             /*
1035*4882a593Smuzhiyun              * Invalid rate
1036*4882a593Smuzhiyun              */
1037*4882a593Smuzhiyun             client->errorValue = rate;
1038*4882a593Smuzhiyun             free(pData);
1039*4882a593Smuzhiyun             return BadValue;
1040*4882a593Smuzhiyun         }
1041*4882a593Smuzhiyun         mode = pSize->pRates[i].mode;
1042*4882a593Smuzhiyun     }
1043*4882a593Smuzhiyun     else
1044*4882a593Smuzhiyun         mode = pSize->pRates[0].mode;
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun     /*
1047*4882a593Smuzhiyun      * Make sure the requested set-time is not older than
1048*4882a593Smuzhiyun      * the last set-time
1049*4882a593Smuzhiyun      */
1050*4882a593Smuzhiyun     if (CompareTimeStamps(time, pScrPriv->lastSetTime) < 0) {
1051*4882a593Smuzhiyun         status = RRSetConfigInvalidTime;
1052*4882a593Smuzhiyun         goto sendReply;
1053*4882a593Smuzhiyun     }
1054*4882a593Smuzhiyun 
1055*4882a593Smuzhiyun     /*
1056*4882a593Smuzhiyun      * If the screen size is changing, adjust all of the other outputs
1057*4882a593Smuzhiyun      * to fit the new size, mirroring as much as possible
1058*4882a593Smuzhiyun      */
1059*4882a593Smuzhiyun     width = mode->mode.width;
1060*4882a593Smuzhiyun     height = mode->mode.height;
1061*4882a593Smuzhiyun     if (width < pScrPriv->minWidth || pScrPriv->maxWidth < width) {
1062*4882a593Smuzhiyun         client->errorValue = width;
1063*4882a593Smuzhiyun         free(pData);
1064*4882a593Smuzhiyun         return BadValue;
1065*4882a593Smuzhiyun     }
1066*4882a593Smuzhiyun     if (height < pScrPriv->minHeight || pScrPriv->maxHeight < height) {
1067*4882a593Smuzhiyun         client->errorValue = height;
1068*4882a593Smuzhiyun         free(pData);
1069*4882a593Smuzhiyun         return BadValue;
1070*4882a593Smuzhiyun     }
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun     if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1073*4882a593Smuzhiyun         width = mode->mode.height;
1074*4882a593Smuzhiyun         height = mode->mode.width;
1075*4882a593Smuzhiyun     }
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun     if (width != pScreen->width || height != pScreen->height) {
1078*4882a593Smuzhiyun         int c;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun         for (c = 0; c < pScrPriv->numCrtcs; c++) {
1081*4882a593Smuzhiyun             if (!RRCrtcSet(pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
1082*4882a593Smuzhiyun                            0, NULL)) {
1083*4882a593Smuzhiyun                 status = RRSetConfigFailed;
1084*4882a593Smuzhiyun                 /* XXX recover from failure */
1085*4882a593Smuzhiyun                 goto sendReply;
1086*4882a593Smuzhiyun             }
1087*4882a593Smuzhiyun         }
1088*4882a593Smuzhiyun         if (!RRScreenSizeSet(pScreen, width, height,
1089*4882a593Smuzhiyun                              pScreen->mmWidth, pScreen->mmHeight)) {
1090*4882a593Smuzhiyun             status = RRSetConfigFailed;
1091*4882a593Smuzhiyun             /* XXX recover from failure */
1092*4882a593Smuzhiyun             goto sendReply;
1093*4882a593Smuzhiyun         }
1094*4882a593Smuzhiyun     }
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun     if (!RRCrtcSet(crtc, mode, 0, 0, stuff->rotation, 1, &output))
1097*4882a593Smuzhiyun         status = RRSetConfigFailed;
1098*4882a593Smuzhiyun     else {
1099*4882a593Smuzhiyun         pScrPriv->lastSetTime = time;
1100*4882a593Smuzhiyun         status = RRSetConfigSuccess;
1101*4882a593Smuzhiyun     }
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun     /*
1104*4882a593Smuzhiyun      * XXX Configure other crtcs to mirror as much as possible
1105*4882a593Smuzhiyun      */
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun  sendReply:
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun     free(pData);
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun     rep = (xRRSetScreenConfigReply) {
1112*4882a593Smuzhiyun         .type = X_Reply,
1113*4882a593Smuzhiyun         .status = status,
1114*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
1115*4882a593Smuzhiyun         .length = 0,
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun         .newTimestamp = pScrPriv->lastSetTime.milliseconds,
1118*4882a593Smuzhiyun         .newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds,
1119*4882a593Smuzhiyun         .root = pDraw->pScreen->root->drawable.id,
1120*4882a593Smuzhiyun         /* .subpixelOrder = ?? */
1121*4882a593Smuzhiyun     };
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun     if (client->swapped) {
1124*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
1125*4882a593Smuzhiyun         swapl(&rep.length);
1126*4882a593Smuzhiyun         swapl(&rep.newTimestamp);
1127*4882a593Smuzhiyun         swapl(&rep.newConfigTimestamp);
1128*4882a593Smuzhiyun         swapl(&rep.root);
1129*4882a593Smuzhiyun     }
1130*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRSetScreenConfigReply), &rep);
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun     return Success;
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun static CARD16
RR10CurrentSizeID(ScreenPtr pScreen)1136*4882a593Smuzhiyun RR10CurrentSizeID(ScreenPtr pScreen)
1137*4882a593Smuzhiyun {
1138*4882a593Smuzhiyun     CARD16 sizeID = 0xffff;
1139*4882a593Smuzhiyun     RROutputPtr output = RRFirstOutput(pScreen);
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun     if (output) {
1142*4882a593Smuzhiyun         RR10DataPtr data = RR10GetData(pScreen, output);
1143*4882a593Smuzhiyun 
1144*4882a593Smuzhiyun         if (data) {
1145*4882a593Smuzhiyun             int i;
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun             for (i = 0; i < data->nsize; i++)
1148*4882a593Smuzhiyun                 if (data->sizes[i].width == pScreen->width &&
1149*4882a593Smuzhiyun                     data->sizes[i].height == pScreen->height) {
1150*4882a593Smuzhiyun                     sizeID = (CARD16) i;
1151*4882a593Smuzhiyun                     break;
1152*4882a593Smuzhiyun                 }
1153*4882a593Smuzhiyun             free(data);
1154*4882a593Smuzhiyun         }
1155*4882a593Smuzhiyun     }
1156*4882a593Smuzhiyun     return sizeID;
1157*4882a593Smuzhiyun }
1158