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