Add patch that contain Mali fixes.
[deb_xorg-server.git] / randr / rrinfo.c
1 /*
2 * Copyright © 2006 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23 #include "randrstr.h"
24
25 #ifdef RANDR_10_INTERFACE
26 static RRModePtr
27 RROldModeAdd(RROutputPtr output, RRScreenSizePtr size, int refresh)
28 {
29 ScreenPtr pScreen = output->pScreen;
30
31 rrScrPriv(pScreen);
32 xRRModeInfo modeInfo;
33 char name[100];
34 RRModePtr mode;
35 int i;
36 RRModePtr *modes;
37
38 memset(&modeInfo, '\0', sizeof(modeInfo));
39 snprintf(name, sizeof(name), "%dx%d", size->width, size->height);
40
41 modeInfo.width = size->width;
42 modeInfo.height = size->height;
43 modeInfo.hTotal = size->width;
44 modeInfo.vTotal = size->height;
45 modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
46 (CARD32) refresh);
47 modeInfo.nameLength = strlen(name);
48 mode = RRModeGet(&modeInfo, name);
49 if (!mode)
50 return NULL;
51 for (i = 0; i < output->numModes; i++)
52 if (output->modes[i] == mode) {
53 RRModeDestroy(mode);
54 return mode;
55 }
56
57 if (output->numModes)
58 modes = realloc(output->modes,
59 (output->numModes + 1) * sizeof(RRModePtr));
60 else
61 modes = malloc(sizeof(RRModePtr));
62 if (!modes) {
63 RRModeDestroy(mode);
64 FreeResource(mode->mode.id, 0);
65 return NULL;
66 }
67 modes[output->numModes++] = mode;
68 output->modes = modes;
69 output->changed = TRUE;
70 pScrPriv->changed = TRUE;
71 pScrPriv->configChanged = TRUE;
72 return mode;
73 }
74
75 static void
76 RRScanOldConfig(ScreenPtr pScreen, Rotation rotations)
77 {
78 rrScrPriv(pScreen);
79 RROutputPtr output;
80 RRCrtcPtr crtc;
81 RRModePtr mode, newMode = NULL;
82 int i;
83 CARD16 minWidth = MAXSHORT, minHeight = MAXSHORT;
84 CARD16 maxWidth = 0, maxHeight = 0;
85 CARD16 width, height;
86
87 /*
88 * First time through, create a crtc and output and hook
89 * them together
90 */
91 if (pScrPriv->numOutputs == 0 && pScrPriv->numCrtcs == 0) {
92 crtc = RRCrtcCreate(pScreen, NULL);
93 if (!crtc)
94 return;
95 output = RROutputCreate(pScreen, "default", 7, NULL);
96 if (!output)
97 return;
98 RROutputSetCrtcs(output, &crtc, 1);
99 RROutputSetConnection(output, RR_Connected);
100 RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen));
101 }
102
103 output = pScrPriv->outputs[0];
104 if (!output)
105 return;
106 crtc = pScrPriv->crtcs[0];
107 if (!crtc)
108 return;
109
110 /* check rotations */
111 if (rotations != crtc->rotations) {
112 crtc->rotations = rotations;
113 crtc->changed = TRUE;
114 pScrPriv->changed = TRUE;
115 }
116
117 /* regenerate mode list */
118 for (i = 0; i < pScrPriv->nSizes; i++) {
119 RRScreenSizePtr size = &pScrPriv->pSizes[i];
120 int r;
121
122 if (size->nRates) {
123 for (r = 0; r < size->nRates; r++) {
124 mode = RROldModeAdd(output, size, size->pRates[r].rate);
125 if (i == pScrPriv->size &&
126 size->pRates[r].rate == pScrPriv->rate) {
127 newMode = mode;
128 }
129 }
130 free(size->pRates);
131 }
132 else {
133 mode = RROldModeAdd(output, size, 0);
134 if (i == pScrPriv->size)
135 newMode = mode;
136 }
137 }
138 if (pScrPriv->nSizes)
139 free(pScrPriv->pSizes);
140 pScrPriv->pSizes = NULL;
141 pScrPriv->nSizes = 0;
142
143 /* find size bounds */
144 for (i = 0; i < output->numModes + output->numUserModes; i++) {
145 mode = (i < output->numModes ?
146 output->modes[i] :
147 output->userModes[i - output->numModes]);
148 width = mode->mode.width;
149 height = mode->mode.height;
150
151 if (width < minWidth)
152 minWidth = width;
153 if (width > maxWidth)
154 maxWidth = width;
155 if (height < minHeight)
156 minHeight = height;
157 if (height > maxHeight)
158 maxHeight = height;
159 }
160
161 RRScreenSetSizeRange(pScreen, minWidth, minHeight, maxWidth, maxHeight);
162
163 /* notice current mode */
164 if (newMode)
165 RRCrtcNotify(crtc, newMode, 0, 0, pScrPriv->rotation, NULL, 1, &output);
166 }
167 #endif
168
169 /*
170 * Poll the driver for changed information
171 */
172 Bool
173 RRGetInfo(ScreenPtr pScreen, Bool force_query)
174 {
175 rrScrPriv(pScreen);
176 Rotation rotations;
177 int i;
178
179 /* Return immediately if we don't need to re-query and we already have the
180 * information.
181 */
182 if (!force_query) {
183 if (pScrPriv->numCrtcs != 0 || pScrPriv->numOutputs != 0)
184 return TRUE;
185 }
186
187 for (i = 0; i < pScrPriv->numOutputs; i++)
188 pScrPriv->outputs[i]->changed = FALSE;
189 for (i = 0; i < pScrPriv->numCrtcs; i++)
190 pScrPriv->crtcs[i]->changed = FALSE;
191
192 rotations = 0;
193 pScrPriv->changed = FALSE;
194 pScrPriv->configChanged = FALSE;
195
196 if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
197 return FALSE;
198
199 #if RANDR_10_INTERFACE
200 if (pScrPriv->nSizes)
201 RRScanOldConfig(pScreen, rotations);
202 #endif
203 RRTellChanged(pScreen);
204 return TRUE;
205 }
206
207 /*
208 * Register the range of sizes for the screen
209 */
210 void
211 RRScreenSetSizeRange(ScreenPtr pScreen,
212 CARD16 minWidth,
213 CARD16 minHeight, CARD16 maxWidth, CARD16 maxHeight)
214 {
215 rrScrPriv(pScreen);
216
217 if (!pScrPriv)
218 return;
219 if (pScrPriv->minWidth == minWidth && pScrPriv->minHeight == minHeight &&
220 pScrPriv->maxWidth == maxWidth && pScrPriv->maxHeight == maxHeight) {
221 return;
222 }
223
224 pScrPriv->minWidth = minWidth;
225 pScrPriv->minHeight = minHeight;
226 pScrPriv->maxWidth = maxWidth;
227 pScrPriv->maxHeight = maxHeight;
228 RRSetChanged(pScreen);
229 pScrPriv->configChanged = TRUE;
230 }
231
232 #ifdef RANDR_10_INTERFACE
233 static Bool
234 RRScreenSizeMatches(RRScreenSizePtr a, RRScreenSizePtr b)
235 {
236 if (a->width != b->width)
237 return FALSE;
238 if (a->height != b->height)
239 return FALSE;
240 if (a->mmWidth != b->mmWidth)
241 return FALSE;
242 if (a->mmHeight != b->mmHeight)
243 return FALSE;
244 return TRUE;
245 }
246
247 RRScreenSizePtr
248 RRRegisterSize(ScreenPtr pScreen,
249 short width, short height, short mmWidth, short mmHeight)
250 {
251 rrScrPriv(pScreen);
252 int i;
253 RRScreenSize tmp;
254 RRScreenSizePtr pNew;
255
256 if (!pScrPriv)
257 return 0;
258
259 tmp.id = 0;
260 tmp.width = width;
261 tmp.height = height;
262 tmp.mmWidth = mmWidth;
263 tmp.mmHeight = mmHeight;
264 tmp.pRates = 0;
265 tmp.nRates = 0;
266 for (i = 0; i < pScrPriv->nSizes; i++)
267 if (RRScreenSizeMatches(&tmp, &pScrPriv->pSizes[i]))
268 return &pScrPriv->pSizes[i];
269 pNew = realloc(pScrPriv->pSizes,
270 (pScrPriv->nSizes + 1) * sizeof(RRScreenSize));
271 if (!pNew)
272 return 0;
273 pNew[pScrPriv->nSizes++] = tmp;
274 pScrPriv->pSizes = pNew;
275 return &pNew[pScrPriv->nSizes - 1];
276 }
277
278 Bool
279 RRRegisterRate(ScreenPtr pScreen, RRScreenSizePtr pSize, int rate)
280 {
281 rrScrPriv(pScreen);
282 int i;
283 RRScreenRatePtr pNew, pRate;
284
285 if (!pScrPriv)
286 return FALSE;
287
288 for (i = 0; i < pSize->nRates; i++)
289 if (pSize->pRates[i].rate == rate)
290 return TRUE;
291
292 pNew = realloc(pSize->pRates, (pSize->nRates + 1) * sizeof(RRScreenRate));
293 if (!pNew)
294 return FALSE;
295 pRate = &pNew[pSize->nRates++];
296 pRate->rate = rate;
297 pSize->pRates = pNew;
298 return TRUE;
299 }
300
301 Rotation
302 RRGetRotation(ScreenPtr pScreen)
303 {
304 RROutputPtr output = RRFirstOutput(pScreen);
305
306 if (!output)
307 return RR_Rotate_0;
308
309 return output->crtc->rotation;
310 }
311
312 void
313 RRSetCurrentConfig(ScreenPtr pScreen,
314 Rotation rotation, int rate, RRScreenSizePtr pSize)
315 {
316 rrScrPriv(pScreen);
317
318 if (!pScrPriv)
319 return;
320 pScrPriv->size = pSize - pScrPriv->pSizes;
321 pScrPriv->rotation = rotation;
322 pScrPriv->rate = rate;
323 }
324 #endif