xref: /OK3568_Linux_fs/external/xserver/randr/rrinfo.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 #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