Commit | Line | Data |
---|---|---|
a09e091a JB |
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 |