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 #ifdef RANDR_10_INTERFACE
26*4882a593Smuzhiyun static RRModePtr
RROldModeAdd(RROutputPtr output,RRScreenSizePtr size,int refresh)27*4882a593Smuzhiyun RROldModeAdd(RROutputPtr output, RRScreenSizePtr size, int refresh)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun ScreenPtr pScreen = output->pScreen;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun rrScrPriv(pScreen);
32*4882a593Smuzhiyun xRRModeInfo modeInfo;
33*4882a593Smuzhiyun char name[100];
34*4882a593Smuzhiyun RRModePtr mode;
35*4882a593Smuzhiyun int i;
36*4882a593Smuzhiyun RRModePtr *modes;
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun memset(&modeInfo, '\0', sizeof(modeInfo));
39*4882a593Smuzhiyun snprintf(name, sizeof(name), "%dx%d", size->width, size->height);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun modeInfo.width = size->width;
42*4882a593Smuzhiyun modeInfo.height = size->height;
43*4882a593Smuzhiyun modeInfo.hTotal = size->width;
44*4882a593Smuzhiyun modeInfo.vTotal = size->height;
45*4882a593Smuzhiyun modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
46*4882a593Smuzhiyun (CARD32) refresh);
47*4882a593Smuzhiyun modeInfo.nameLength = strlen(name);
48*4882a593Smuzhiyun mode = RRModeGet(&modeInfo, name);
49*4882a593Smuzhiyun if (!mode)
50*4882a593Smuzhiyun return NULL;
51*4882a593Smuzhiyun for (i = 0; i < output->numModes; i++)
52*4882a593Smuzhiyun if (output->modes[i] == mode) {
53*4882a593Smuzhiyun RRModeDestroy(mode);
54*4882a593Smuzhiyun return mode;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun if (output->numModes)
58*4882a593Smuzhiyun modes = reallocarray(output->modes,
59*4882a593Smuzhiyun output->numModes + 1, sizeof(RRModePtr));
60*4882a593Smuzhiyun else
61*4882a593Smuzhiyun modes = malloc(sizeof(RRModePtr));
62*4882a593Smuzhiyun if (!modes) {
63*4882a593Smuzhiyun RRModeDestroy(mode);
64*4882a593Smuzhiyun FreeResource(mode->mode.id, 0);
65*4882a593Smuzhiyun return NULL;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun modes[output->numModes++] = mode;
68*4882a593Smuzhiyun output->modes = modes;
69*4882a593Smuzhiyun output->changed = TRUE;
70*4882a593Smuzhiyun pScrPriv->changed = TRUE;
71*4882a593Smuzhiyun pScrPriv->configChanged = TRUE;
72*4882a593Smuzhiyun return mode;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun static void
RRScanOldConfig(ScreenPtr pScreen,Rotation rotations)76*4882a593Smuzhiyun RRScanOldConfig(ScreenPtr pScreen, Rotation rotations)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun rrScrPriv(pScreen);
79*4882a593Smuzhiyun RROutputPtr output;
80*4882a593Smuzhiyun RRCrtcPtr crtc;
81*4882a593Smuzhiyun RRModePtr mode, newMode = NULL;
82*4882a593Smuzhiyun int i;
83*4882a593Smuzhiyun CARD16 minWidth = MAXSHORT, minHeight = MAXSHORT;
84*4882a593Smuzhiyun CARD16 maxWidth = 0, maxHeight = 0;
85*4882a593Smuzhiyun CARD16 width, height;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /*
88*4882a593Smuzhiyun * First time through, create a crtc and output and hook
89*4882a593Smuzhiyun * them together
90*4882a593Smuzhiyun */
91*4882a593Smuzhiyun if (pScrPriv->numOutputs == 0 && pScrPriv->numCrtcs == 0) {
92*4882a593Smuzhiyun crtc = RRCrtcCreate(pScreen, NULL);
93*4882a593Smuzhiyun if (!crtc)
94*4882a593Smuzhiyun return;
95*4882a593Smuzhiyun output = RROutputCreate(pScreen, "default", 7, NULL);
96*4882a593Smuzhiyun if (!output)
97*4882a593Smuzhiyun return;
98*4882a593Smuzhiyun RROutputSetCrtcs(output, &crtc, 1);
99*4882a593Smuzhiyun RROutputSetConnection(output, RR_Connected);
100*4882a593Smuzhiyun RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen));
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun output = pScrPriv->outputs[0];
104*4882a593Smuzhiyun if (!output)
105*4882a593Smuzhiyun return;
106*4882a593Smuzhiyun crtc = pScrPriv->crtcs[0];
107*4882a593Smuzhiyun if (!crtc)
108*4882a593Smuzhiyun return;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* check rotations */
111*4882a593Smuzhiyun if (rotations != crtc->rotations) {
112*4882a593Smuzhiyun crtc->rotations = rotations;
113*4882a593Smuzhiyun crtc->changed = TRUE;
114*4882a593Smuzhiyun pScrPriv->changed = TRUE;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /* regenerate mode list */
118*4882a593Smuzhiyun for (i = 0; i < pScrPriv->nSizes; i++) {
119*4882a593Smuzhiyun RRScreenSizePtr size = &pScrPriv->pSizes[i];
120*4882a593Smuzhiyun int r;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun if (size->nRates) {
123*4882a593Smuzhiyun for (r = 0; r < size->nRates; r++) {
124*4882a593Smuzhiyun mode = RROldModeAdd(output, size, size->pRates[r].rate);
125*4882a593Smuzhiyun if (i == pScrPriv->size &&
126*4882a593Smuzhiyun size->pRates[r].rate == pScrPriv->rate) {
127*4882a593Smuzhiyun newMode = mode;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun free(size->pRates);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun else {
133*4882a593Smuzhiyun mode = RROldModeAdd(output, size, 0);
134*4882a593Smuzhiyun if (i == pScrPriv->size)
135*4882a593Smuzhiyun newMode = mode;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun if (pScrPriv->nSizes)
139*4882a593Smuzhiyun free(pScrPriv->pSizes);
140*4882a593Smuzhiyun pScrPriv->pSizes = NULL;
141*4882a593Smuzhiyun pScrPriv->nSizes = 0;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* find size bounds */
144*4882a593Smuzhiyun for (i = 0; i < output->numModes + output->numUserModes; i++) {
145*4882a593Smuzhiyun mode = (i < output->numModes ?
146*4882a593Smuzhiyun output->modes[i] :
147*4882a593Smuzhiyun output->userModes[i - output->numModes]);
148*4882a593Smuzhiyun width = mode->mode.width;
149*4882a593Smuzhiyun height = mode->mode.height;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (width < minWidth)
152*4882a593Smuzhiyun minWidth = width;
153*4882a593Smuzhiyun if (width > maxWidth)
154*4882a593Smuzhiyun maxWidth = width;
155*4882a593Smuzhiyun if (height < minHeight)
156*4882a593Smuzhiyun minHeight = height;
157*4882a593Smuzhiyun if (height > maxHeight)
158*4882a593Smuzhiyun maxHeight = height;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun RRScreenSetSizeRange(pScreen, minWidth, minHeight, maxWidth, maxHeight);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /* notice current mode */
164*4882a593Smuzhiyun if (newMode)
165*4882a593Smuzhiyun RRCrtcNotify(crtc, newMode, 0, 0, pScrPriv->rotation, NULL, 1, &output);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun #endif
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /*
170*4882a593Smuzhiyun * Poll the driver for changed information
171*4882a593Smuzhiyun */
172*4882a593Smuzhiyun Bool
RRGetInfo(ScreenPtr pScreen,Bool force_query)173*4882a593Smuzhiyun RRGetInfo(ScreenPtr pScreen, Bool force_query)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun rrScrPriv(pScreen);
176*4882a593Smuzhiyun Rotation rotations;
177*4882a593Smuzhiyun int i;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /* Return immediately if we don't need to re-query and we already have the
180*4882a593Smuzhiyun * information.
181*4882a593Smuzhiyun */
182*4882a593Smuzhiyun if (!force_query) {
183*4882a593Smuzhiyun if (pScrPriv->numCrtcs != 0 || pScrPriv->numOutputs != 0)
184*4882a593Smuzhiyun return TRUE;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun for (i = 0; i < pScrPriv->numOutputs; i++)
188*4882a593Smuzhiyun pScrPriv->outputs[i]->changed = FALSE;
189*4882a593Smuzhiyun for (i = 0; i < pScrPriv->numCrtcs; i++)
190*4882a593Smuzhiyun pScrPriv->crtcs[i]->changed = FALSE;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun rotations = 0;
193*4882a593Smuzhiyun pScrPriv->changed = FALSE;
194*4882a593Smuzhiyun pScrPriv->configChanged = FALSE;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
197*4882a593Smuzhiyun return FALSE;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #if RANDR_10_INTERFACE
200*4882a593Smuzhiyun if (pScrPriv->nSizes)
201*4882a593Smuzhiyun RRScanOldConfig(pScreen, rotations);
202*4882a593Smuzhiyun #endif
203*4882a593Smuzhiyun RRTellChanged(pScreen);
204*4882a593Smuzhiyun return TRUE;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun * Register the range of sizes for the screen
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun void
RRScreenSetSizeRange(ScreenPtr pScreen,CARD16 minWidth,CARD16 minHeight,CARD16 maxWidth,CARD16 maxHeight)211*4882a593Smuzhiyun RRScreenSetSizeRange(ScreenPtr pScreen,
212*4882a593Smuzhiyun CARD16 minWidth,
213*4882a593Smuzhiyun CARD16 minHeight, CARD16 maxWidth, CARD16 maxHeight)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun rrScrPriv(pScreen);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun if (!pScrPriv)
218*4882a593Smuzhiyun return;
219*4882a593Smuzhiyun if (pScrPriv->minWidth == minWidth && pScrPriv->minHeight == minHeight &&
220*4882a593Smuzhiyun pScrPriv->maxWidth == maxWidth && pScrPriv->maxHeight == maxHeight) {
221*4882a593Smuzhiyun return;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun pScrPriv->minWidth = minWidth;
225*4882a593Smuzhiyun pScrPriv->minHeight = minHeight;
226*4882a593Smuzhiyun pScrPriv->maxWidth = maxWidth;
227*4882a593Smuzhiyun pScrPriv->maxHeight = maxHeight;
228*4882a593Smuzhiyun RRSetChanged(pScreen);
229*4882a593Smuzhiyun pScrPriv->configChanged = TRUE;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun #ifdef RANDR_10_INTERFACE
233*4882a593Smuzhiyun static Bool
RRScreenSizeMatches(RRScreenSizePtr a,RRScreenSizePtr b)234*4882a593Smuzhiyun RRScreenSizeMatches(RRScreenSizePtr a, RRScreenSizePtr b)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun if (a->width != b->width)
237*4882a593Smuzhiyun return FALSE;
238*4882a593Smuzhiyun if (a->height != b->height)
239*4882a593Smuzhiyun return FALSE;
240*4882a593Smuzhiyun if (a->mmWidth != b->mmWidth)
241*4882a593Smuzhiyun return FALSE;
242*4882a593Smuzhiyun if (a->mmHeight != b->mmHeight)
243*4882a593Smuzhiyun return FALSE;
244*4882a593Smuzhiyun return TRUE;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun RRScreenSizePtr
RRRegisterSize(ScreenPtr pScreen,short width,short height,short mmWidth,short mmHeight)248*4882a593Smuzhiyun RRRegisterSize(ScreenPtr pScreen,
249*4882a593Smuzhiyun short width, short height, short mmWidth, short mmHeight)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun rrScrPriv(pScreen);
252*4882a593Smuzhiyun int i;
253*4882a593Smuzhiyun RRScreenSize tmp;
254*4882a593Smuzhiyun RRScreenSizePtr pNew;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (!pScrPriv)
257*4882a593Smuzhiyun return 0;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun tmp.id = 0;
260*4882a593Smuzhiyun tmp.width = width;
261*4882a593Smuzhiyun tmp.height = height;
262*4882a593Smuzhiyun tmp.mmWidth = mmWidth;
263*4882a593Smuzhiyun tmp.mmHeight = mmHeight;
264*4882a593Smuzhiyun tmp.pRates = 0;
265*4882a593Smuzhiyun tmp.nRates = 0;
266*4882a593Smuzhiyun for (i = 0; i < pScrPriv->nSizes; i++)
267*4882a593Smuzhiyun if (RRScreenSizeMatches(&tmp, &pScrPriv->pSizes[i]))
268*4882a593Smuzhiyun return &pScrPriv->pSizes[i];
269*4882a593Smuzhiyun pNew = reallocarray(pScrPriv->pSizes,
270*4882a593Smuzhiyun pScrPriv->nSizes + 1, sizeof(RRScreenSize));
271*4882a593Smuzhiyun if (!pNew)
272*4882a593Smuzhiyun return 0;
273*4882a593Smuzhiyun pNew[pScrPriv->nSizes++] = tmp;
274*4882a593Smuzhiyun pScrPriv->pSizes = pNew;
275*4882a593Smuzhiyun return &pNew[pScrPriv->nSizes - 1];
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun Bool
RRRegisterRate(ScreenPtr pScreen,RRScreenSizePtr pSize,int rate)279*4882a593Smuzhiyun RRRegisterRate(ScreenPtr pScreen, RRScreenSizePtr pSize, int rate)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun rrScrPriv(pScreen);
282*4882a593Smuzhiyun int i;
283*4882a593Smuzhiyun RRScreenRatePtr pNew, pRate;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun if (!pScrPriv)
286*4882a593Smuzhiyun return FALSE;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun for (i = 0; i < pSize->nRates; i++)
289*4882a593Smuzhiyun if (pSize->pRates[i].rate == rate)
290*4882a593Smuzhiyun return TRUE;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun pNew = reallocarray(pSize->pRates, pSize->nRates + 1, sizeof(RRScreenRate));
293*4882a593Smuzhiyun if (!pNew)
294*4882a593Smuzhiyun return FALSE;
295*4882a593Smuzhiyun pRate = &pNew[pSize->nRates++];
296*4882a593Smuzhiyun pRate->rate = rate;
297*4882a593Smuzhiyun pSize->pRates = pNew;
298*4882a593Smuzhiyun return TRUE;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun Rotation
RRGetRotation(ScreenPtr pScreen)302*4882a593Smuzhiyun RRGetRotation(ScreenPtr pScreen)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun RROutputPtr output = RRFirstOutput(pScreen);
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun if (!output)
307*4882a593Smuzhiyun return RR_Rotate_0;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun return output->crtc->rotation;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun void
RRSetCurrentConfig(ScreenPtr pScreen,Rotation rotation,int rate,RRScreenSizePtr pSize)313*4882a593Smuzhiyun RRSetCurrentConfig(ScreenPtr pScreen,
314*4882a593Smuzhiyun Rotation rotation, int rate, RRScreenSizePtr pSize)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun rrScrPriv(pScreen);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun if (!pScrPriv)
319*4882a593Smuzhiyun return;
320*4882a593Smuzhiyun pScrPriv->size = pSize - pScrPriv->pSizes;
321*4882a593Smuzhiyun pScrPriv->rotation = rotation;
322*4882a593Smuzhiyun pScrPriv->rate = rate;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun #endif
325