File: | hw/xfree86/modes/xf86Crtc.c |
Location: | line 2366, column 9 |
Description: | Value stored to 'output' is never read |
1 | /* |
2 | * Copyright © 2006 Keith Packard |
3 | * Copyright © 2008 Red Hat, Inc. |
4 | * |
5 | * Permission to use, copy, modify, distribute, and sell this software and its |
6 | * documentation for any purpose is hereby granted without fee, provided that |
7 | * the above copyright notice appear in all copies and that both that copyright |
8 | * notice and this permission notice appear in supporting documentation, and |
9 | * that the name of the copyright holders not be used in advertising or |
10 | * publicity pertaining to distribution of the software without specific, |
11 | * written prior permission. The copyright holders make no representations |
12 | * about the suitability of this software for any purpose. It is provided "as |
13 | * is" without express or implied warranty. |
14 | * |
15 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
16 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
17 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
18 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
19 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
20 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
21 | * OF THIS SOFTWARE. |
22 | */ |
23 | |
24 | #ifdef HAVE_XORG_CONFIG_H1 |
25 | #include <xorg-config.h> |
26 | #else |
27 | #ifdef HAVE_CONFIG_H1 |
28 | #include <config.h> |
29 | #endif |
30 | #endif |
31 | |
32 | #include <stddef.h> |
33 | #include <string.h> |
34 | #include <stdio.h> |
35 | |
36 | #include "xf86.h" |
37 | #include "xf86DDC.h" |
38 | #include "xf86Crtc.h" |
39 | #include "xf86Modes.h" |
40 | #include "xf86Priv.h" |
41 | #include "xf86RandR12.h" |
42 | #include "X11/extensions/render.h" |
43 | #include "X11/extensions/dpmsconst.h" |
44 | #include "X11/Xatom.h" |
45 | #include "picturestr.h" |
46 | |
47 | #ifdef XV1 |
48 | #include "xf86xv.h" |
49 | #endif |
50 | |
51 | #define NO_OUTPUT_DEFAULT_WIDTH1024 1024 |
52 | #define NO_OUTPUT_DEFAULT_HEIGHT768 768 |
53 | /* |
54 | * Initialize xf86CrtcConfig structure |
55 | */ |
56 | |
57 | int xf86CrtcConfigPrivateIndex = -1; |
58 | |
59 | void |
60 | xf86CrtcConfigInit(ScrnInfoPtr scrn, const xf86CrtcConfigFuncsRec * funcs) |
61 | { |
62 | xf86CrtcConfigPtr config; |
63 | |
64 | if (xf86CrtcConfigPrivateIndex == -1) |
65 | xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); |
66 | config = xnfcalloc(1, sizeof(xf86CrtcConfigRec))XNFcallocarray((1), (sizeof(xf86CrtcConfigRec))); |
67 | |
68 | config->funcs = funcs; |
69 | config->compat_output = -1; |
70 | |
71 | scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; |
72 | } |
73 | |
74 | void |
75 | xf86CrtcSetSizeRange(ScrnInfoPtr scrn, |
76 | int minWidth, int minHeight, int maxWidth, int maxHeight) |
77 | { |
78 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
79 | |
80 | config->minWidth = minWidth; |
81 | config->minHeight = minHeight; |
82 | config->maxWidth = maxWidth; |
83 | config->maxHeight = maxHeight; |
84 | } |
85 | |
86 | /* |
87 | * Crtc functions |
88 | */ |
89 | xf86CrtcPtr |
90 | xf86CrtcCreate(ScrnInfoPtr scrn, const xf86CrtcFuncsRec * funcs) |
91 | { |
92 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
93 | xf86CrtcPtr crtc, *crtcs; |
94 | |
95 | crtc = calloc(sizeof(xf86CrtcRec), 1); |
96 | if (!crtc) |
97 | return NULL((void*)0); |
98 | crtc->version = XF86_CRTC_VERSION6; |
99 | crtc->scrn = scrn; |
100 | crtc->funcs = funcs; |
101 | #ifdef RANDR_12_INTERFACE1 |
102 | crtc->randr_crtc = NULL((void*)0); |
103 | #endif |
104 | crtc->rotation = RR_Rotate_01; |
105 | crtc->desiredRotation = RR_Rotate_01; |
106 | pixman_transform_init_identity(&crtc->crtc_to_framebuffer); |
107 | pixman_f_transform_init_identity(&crtc->f_crtc_to_framebuffer); |
108 | pixman_f_transform_init_identity(&crtc->f_framebuffer_to_crtc); |
109 | crtc->filter = NULL((void*)0); |
110 | crtc->params = NULL((void*)0); |
111 | crtc->nparams = 0; |
112 | crtc->filter_width = 0; |
113 | crtc->filter_height = 0; |
114 | crtc->transform_in_use = FALSE0; |
115 | crtc->transformPresent = FALSE0; |
116 | crtc->desiredTransformPresent = FALSE0; |
117 | memset(&crtc->bounds, '\0', sizeof(crtc->bounds))__builtin___memset_chk (&crtc->bounds, '\0', sizeof(crtc ->bounds), __builtin_object_size (&crtc->bounds, 0) ); |
118 | |
119 | /* Preallocate gamma at a sensible size. */ |
120 | crtc->gamma_size = 256; |
121 | crtc->gamma_red = xallocarray(crtc->gamma_size, 3 * sizeof(CARD16))xreallocarray(((void*)0), (crtc->gamma_size), (3 * sizeof( CARD16))); |
122 | if (!crtc->gamma_red) { |
123 | free(crtc); |
124 | return NULL((void*)0); |
125 | } |
126 | crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; |
127 | crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; |
128 | |
129 | if (xf86_config->crtc) |
130 | crtcs = reallocarrayxreallocarray(xf86_config->crtc, |
131 | xf86_config->num_crtc + 1, sizeof(xf86CrtcPtr)); |
132 | else |
133 | crtcs = xallocarray(xf86_config->num_crtc + 1, sizeof(xf86CrtcPtr))xreallocarray(((void*)0), (xf86_config->num_crtc + 1), (sizeof (xf86CrtcPtr))); |
134 | if (!crtcs) { |
135 | free(crtc->gamma_red); |
136 | free(crtc); |
137 | return NULL((void*)0); |
138 | } |
139 | xf86_config->crtc = crtcs; |
140 | xf86_config->crtc[xf86_config->num_crtc++] = crtc; |
141 | return crtc; |
142 | } |
143 | |
144 | void |
145 | xf86CrtcDestroy(xf86CrtcPtr crtc) |
146 | { |
147 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn)((xf86CrtcConfigPtr) ((crtc->scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
148 | int c; |
149 | |
150 | (*crtc->funcs->destroy) (crtc); |
151 | for (c = 0; c < xf86_config->num_crtc; c++) |
152 | if (xf86_config->crtc[c] == crtc) { |
153 | memmove(&xf86_config->crtc[c],__builtin___memmove_chk (&xf86_config->crtc[c], &xf86_config ->crtc[c + 1], ((xf86_config->num_crtc - (c + 1)) * sizeof (void *)), __builtin_object_size (&xf86_config->crtc[c ], 0)) |
154 | &xf86_config->crtc[c + 1],__builtin___memmove_chk (&xf86_config->crtc[c], &xf86_config ->crtc[c + 1], ((xf86_config->num_crtc - (c + 1)) * sizeof (void *)), __builtin_object_size (&xf86_config->crtc[c ], 0)) |
155 | ((xf86_config->num_crtc - (c + 1)) * sizeof(void *)))__builtin___memmove_chk (&xf86_config->crtc[c], &xf86_config ->crtc[c + 1], ((xf86_config->num_crtc - (c + 1)) * sizeof (void *)), __builtin_object_size (&xf86_config->crtc[c ], 0)); |
156 | xf86_config->num_crtc--; |
157 | break; |
158 | } |
159 | free(crtc->params); |
160 | free(crtc->gamma_red); |
161 | free(crtc); |
162 | } |
163 | |
164 | /** |
165 | * Return whether any outputs are connected to the specified pipe |
166 | */ |
167 | |
168 | Bool |
169 | xf86CrtcInUse(xf86CrtcPtr crtc) |
170 | { |
171 | ScrnInfoPtr pScrn = crtc->scrn; |
172 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
173 | int o; |
174 | |
175 | for (o = 0; o < xf86_config->num_output; o++) |
176 | if (xf86_config->output[o]->crtc == crtc) |
177 | return TRUE1; |
178 | return FALSE0; |
179 | } |
180 | |
181 | void |
182 | xf86CrtcSetScreenSubpixelOrder(ScreenPtr pScreen) |
183 | { |
184 | int subpixel_order = SubPixelUnknown0; |
185 | Bool has_none = FALSE0; |
186 | ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); |
187 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
188 | int icrtc, o; |
189 | |
190 | for (icrtc = 0; icrtc < xf86_config->num_crtc; icrtc++) { |
191 | xf86CrtcPtr crtc = xf86_config->crtc[icrtc]; |
192 | |
193 | for (o = 0; o < xf86_config->num_output; o++) { |
194 | xf86OutputPtr output = xf86_config->output[o]; |
195 | |
196 | if (output->crtc == crtc) { |
197 | switch (output->subpixel_order) { |
198 | case SubPixelNone5: |
199 | has_none = TRUE1; |
200 | break; |
201 | case SubPixelUnknown0: |
202 | break; |
203 | default: |
204 | subpixel_order = output->subpixel_order; |
205 | break; |
206 | } |
207 | } |
208 | if (subpixel_order != SubPixelUnknown0) |
209 | break; |
210 | } |
211 | if (subpixel_order != SubPixelUnknown0) { |
212 | static const int circle[4] = { |
213 | SubPixelHorizontalRGB1, |
214 | SubPixelVerticalRGB3, |
215 | SubPixelHorizontalBGR2, |
216 | SubPixelVerticalBGR4, |
217 | }; |
218 | int rotate; |
219 | int sc; |
220 | |
221 | for (rotate = 0; rotate < 4; rotate++) |
222 | if (crtc->rotation & (1 << rotate)) |
223 | break; |
224 | for (sc = 0; sc < 4; sc++) |
225 | if (circle[sc] == subpixel_order) |
226 | break; |
227 | sc = (sc + rotate) & 0x3; |
228 | if ((crtc->rotation & RR_Reflect_X16) && !(sc & 1)) |
229 | sc ^= 2; |
230 | if ((crtc->rotation & RR_Reflect_Y32) && (sc & 1)) |
231 | sc ^= 2; |
232 | subpixel_order = circle[sc]; |
233 | break; |
234 | } |
235 | } |
236 | if (subpixel_order == SubPixelUnknown0 && has_none) |
237 | subpixel_order = SubPixelNone5; |
238 | PictureSetSubpixelOrder(pScreen, subpixel_order); |
239 | } |
240 | |
241 | /** |
242 | * Sets the given video mode on the given crtc |
243 | */ |
244 | Bool |
245 | xf86CrtcSetModeTransform(xf86CrtcPtr crtc, DisplayModePtr mode, |
246 | Rotation rotation, RRTransformPtr transform, int x, |
247 | int y) |
248 | { |
249 | ScrnInfoPtr scrn = crtc->scrn; |
250 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
251 | int i; |
252 | Bool ret = FALSE0; |
253 | Bool didLock = FALSE0; |
254 | DisplayModePtr adjusted_mode; |
255 | DisplayModeRec saved_mode; |
256 | int saved_x, saved_y; |
257 | Rotation saved_rotation; |
258 | RRTransformRec saved_transform; |
259 | Bool saved_transform_present; |
260 | |
261 | crtc->enabled = xf86CrtcInUse(crtc); |
262 | |
263 | /* We only hit this if someone explicitly sends a "disabled" modeset. */ |
264 | if (!crtc->enabled) { |
265 | /* Check everything for stuff that should be off. */ |
266 | xf86DisableUnusedFunctions(scrn); |
267 | return TRUE1; |
268 | } |
269 | |
270 | adjusted_mode = xf86DuplicateMode(mode); |
271 | |
272 | saved_mode = crtc->mode; |
273 | saved_x = crtc->x; |
274 | saved_y = crtc->y; |
275 | saved_rotation = crtc->rotation; |
276 | if (crtc->transformPresent) { |
277 | RRTransformInit(&saved_transform); |
278 | RRTransformCopy(&saved_transform, &crtc->transform); |
279 | } |
280 | saved_transform_present = crtc->transformPresent; |
281 | |
282 | /* Update crtc values up front so the driver can rely on them for mode |
283 | * setting. |
284 | */ |
285 | crtc->mode = *mode; |
286 | crtc->x = x; |
287 | crtc->y = y; |
288 | crtc->rotation = rotation; |
289 | if (transform) { |
290 | RRTransformCopy(&crtc->transform, transform); |
291 | crtc->transformPresent = TRUE1; |
292 | } |
293 | else |
294 | crtc->transformPresent = FALSE0; |
295 | |
296 | if (crtc->funcs->set_mode_major) { |
297 | ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); |
298 | goto done; |
299 | } |
300 | |
301 | didLock = crtc->funcs->lock(crtc); |
302 | /* Pass our mode to the outputs and the CRTC to give them a chance to |
303 | * adjust it according to limitations or output properties, and also |
304 | * a chance to reject the mode entirely. |
305 | */ |
306 | for (i = 0; i < xf86_config->num_output; i++) { |
307 | xf86OutputPtr output = xf86_config->output[i]; |
308 | |
309 | if (output->crtc != crtc) |
310 | continue; |
311 | |
312 | if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { |
313 | goto done; |
314 | } |
315 | } |
316 | |
317 | if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { |
318 | goto done; |
319 | } |
320 | |
321 | if (!xf86CrtcRotate(crtc)) |
322 | goto done; |
323 | |
324 | /* Prepare the outputs and CRTCs before setting the mode. */ |
325 | for (i = 0; i < xf86_config->num_output; i++) { |
326 | xf86OutputPtr output = xf86_config->output[i]; |
327 | |
328 | if (output->crtc != crtc) |
329 | continue; |
330 | |
331 | /* Disable the output as the first thing we do. */ |
332 | output->funcs->prepare(output); |
333 | } |
334 | |
335 | crtc->funcs->prepare(crtc); |
336 | |
337 | /* Set up the DPLL and any output state that needs to adjust or depend |
338 | * on the DPLL. |
339 | */ |
340 | crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y); |
341 | for (i = 0; i < xf86_config->num_output; i++) { |
342 | xf86OutputPtr output = xf86_config->output[i]; |
343 | |
344 | if (output->crtc == crtc) |
345 | output->funcs->mode_set(output, mode, adjusted_mode); |
346 | } |
347 | |
348 | /* Only upload when needed, to avoid unneeded delays. */ |
349 | if (!crtc->active && crtc->funcs->gamma_set) |
350 | crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, |
351 | crtc->gamma_blue, crtc->gamma_size); |
352 | |
353 | /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ |
354 | crtc->funcs->commit(crtc); |
355 | for (i = 0; i < xf86_config->num_output; i++) { |
356 | xf86OutputPtr output = xf86_config->output[i]; |
357 | |
358 | if (output->crtc == crtc) |
359 | output->funcs->commit(output); |
360 | } |
361 | |
362 | ret = TRUE1; |
363 | |
364 | done: |
365 | if (ret) { |
366 | crtc->active = TRUE1; |
367 | if (scrn->pScreen) |
368 | xf86CrtcSetScreenSubpixelOrder(scrn->pScreen); |
369 | if (scrn->ModeSet) |
370 | scrn->ModeSet(scrn); |
371 | |
372 | /* Make sure the HW cursor is hidden if it's supposed to be, in case |
373 | * it was hidden while the CRTC was disabled |
374 | */ |
375 | if (!xf86_config->cursor_on) |
376 | xf86_hide_cursors(scrn); |
377 | } |
378 | else { |
379 | crtc->x = saved_x; |
380 | crtc->y = saved_y; |
381 | crtc->rotation = saved_rotation; |
382 | crtc->mode = saved_mode; |
383 | if (saved_transform_present) |
384 | RRTransformCopy(&crtc->transform, &saved_transform); |
385 | crtc->transformPresent = saved_transform_present; |
386 | } |
387 | |
388 | free((void *) adjusted_mode->name); |
389 | free(adjusted_mode); |
390 | |
391 | if (didLock) |
392 | crtc->funcs->unlock(crtc); |
393 | |
394 | return ret; |
395 | } |
396 | |
397 | /** |
398 | * Sets the given video mode on the given crtc, but without providing |
399 | * a transform |
400 | */ |
401 | Bool |
402 | xf86CrtcSetMode(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, |
403 | int x, int y) |
404 | { |
405 | return xf86CrtcSetModeTransform(crtc, mode, rotation, NULL((void*)0), x, y); |
406 | } |
407 | |
408 | /** |
409 | * Pans the screen, does not change the mode |
410 | */ |
411 | void |
412 | xf86CrtcSetOrigin(xf86CrtcPtr crtc, int x, int y) |
413 | { |
414 | ScrnInfoPtr scrn = crtc->scrn; |
415 | |
416 | crtc->x = x; |
417 | crtc->y = y; |
418 | if (crtc->funcs->set_origin) { |
419 | if (!xf86CrtcRotate(crtc)) |
420 | return; |
421 | crtc->funcs->set_origin(crtc, x, y); |
422 | if (scrn->ModeSet) |
423 | scrn->ModeSet(scrn); |
424 | } |
425 | else |
426 | xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, x, y); |
427 | } |
428 | |
429 | /* |
430 | * Output functions |
431 | */ |
432 | |
433 | extern XF86ConfigPtr xf86configptr; |
434 | |
435 | typedef enum { |
436 | OPTION_PREFERRED_MODE, |
437 | OPTION_ZOOM_MODES, |
438 | OPTION_POSITION, |
439 | OPTION_BELOW, |
440 | OPTION_RIGHT_OF, |
441 | OPTION_ABOVE, |
442 | OPTION_LEFT_OF, |
443 | OPTION_ENABLE, |
444 | OPTION_DISABLE, |
445 | OPTION_MIN_CLOCK, |
446 | OPTION_MAX_CLOCK, |
447 | OPTION_IGNORE, |
448 | OPTION_ROTATE, |
449 | OPTION_PANNING, |
450 | OPTION_PRIMARY, |
451 | OPTION_DEFAULT_MODES, |
452 | } OutputOpts; |
453 | |
454 | static OptionInfoRec xf86OutputOptions[] = { |
455 | {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE0}, |
456 | {OPTION_ZOOM_MODES, "ZoomModes", OPTV_STRING, {0}, FALSE0 }, |
457 | {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE0}, |
458 | {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE0}, |
459 | {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE0}, |
460 | {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE0}, |
461 | {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE0}, |
462 | {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE0}, |
463 | {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE0}, |
464 | {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE0}, |
465 | {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE0}, |
466 | {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE0}, |
467 | {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE0}, |
468 | {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE0}, |
469 | {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE0}, |
470 | {OPTION_DEFAULT_MODES, "DefaultModes", OPTV_BOOLEAN, {0}, FALSE0}, |
471 | {-1, NULL((void*)0), OPTV_NONE, {0}, FALSE0}, |
472 | }; |
473 | |
474 | enum { |
475 | OPTION_MODEDEBUG, |
476 | }; |
477 | |
478 | static OptionInfoRec xf86DeviceOptions[] = { |
479 | {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE0}, |
480 | {-1, NULL((void*)0), OPTV_NONE, {0}, FALSE0}, |
481 | }; |
482 | |
483 | static void |
484 | xf86OutputSetMonitor(xf86OutputPtr output) |
485 | { |
486 | char *option_name; |
487 | const char *monitor; |
488 | |
489 | if (!output->name) |
490 | return; |
491 | |
492 | free(output->options); |
493 | |
494 | output->options = xnfalloc(sizeof(xf86OutputOptions))XNFalloc((unsigned long)(sizeof(xf86OutputOptions))); |
495 | memcpy(output->options, xf86OutputOptions, sizeof(xf86OutputOptions))__builtin___memcpy_chk (output->options, xf86OutputOptions , sizeof(xf86OutputOptions), __builtin_object_size (output-> options, 0)); |
496 | |
497 | XNFasprintf(&option_name, "monitor-%s", output->name); |
498 | monitor = xf86findOptionValue(output->scrn->options, option_name); |
499 | if (!monitor) |
500 | monitor = output->name; |
501 | else |
502 | xf86MarkOptionUsedByName(output->scrn->options, option_name); |
503 | free(option_name); |
504 | output->conf_monitor = xf86findMonitor(monitor, |
505 | xf86configptr->conf_monitor_lst); |
506 | /* |
507 | * Find the monitor section of the screen and use that |
508 | */ |
509 | if (!output->conf_monitor && output->use_screen_monitor) |
510 | output->conf_monitor = xf86findMonitor(output->scrn->monitor->id, |
511 | xf86configptr->conf_monitor_lst); |
512 | if (output->conf_monitor) { |
513 | xf86DrvMsg(output->scrn->scrnIndex, X_INFO, |
514 | "Output %s using monitor section %s\n", |
515 | output->name, output->conf_monitor->mon_identifier); |
516 | xf86ProcessOptions(output->scrn->scrnIndex, |
517 | output->conf_monitor->mon_option_lst, |
518 | output->options); |
519 | } |
520 | else |
521 | xf86DrvMsg(output->scrn->scrnIndex, X_INFO, |
522 | "Output %s has no monitor section\n", output->name); |
523 | } |
524 | |
525 | static Bool |
526 | xf86OutputEnabled(xf86OutputPtr output, Bool strict) |
527 | { |
528 | Bool enable, disable; |
529 | |
530 | /* check to see if this output was enabled in the config file */ |
531 | if (xf86GetOptValBool(output->options, OPTION_ENABLE, &enable) && enable) { |
532 | xf86DrvMsg(output->scrn->scrnIndex, X_INFO, |
533 | "Output %s enabled by config file\n", output->name); |
534 | return TRUE1; |
535 | } |
536 | /* or if this output was disabled in the config file */ |
537 | if (xf86GetOptValBool(output->options, OPTION_DISABLE, &disable) && disable) { |
538 | xf86DrvMsg(output->scrn->scrnIndex, X_INFO, |
539 | "Output %s disabled by config file\n", output->name); |
540 | return FALSE0; |
541 | } |
542 | |
543 | /* If not, try to only light up the ones we know are connected */ |
544 | if (strict) { |
545 | enable = output->status == XF86OutputStatusConnected; |
546 | } |
547 | /* But if that fails, try to light up even outputs we're unsure of */ |
548 | else { |
549 | enable = output->status != XF86OutputStatusDisconnected; |
550 | } |
551 | |
552 | xf86DrvMsg(output->scrn->scrnIndex, X_INFO, |
553 | "Output %s %sconnected\n", output->name, enable ? "" : "dis"); |
554 | return enable; |
555 | } |
556 | |
557 | static Bool |
558 | xf86OutputIgnored(xf86OutputPtr output) |
559 | { |
560 | return xf86ReturnOptValBool(output->options, OPTION_IGNORE, FALSE0); |
561 | } |
562 | |
563 | static const char *direction[4] = { |
564 | "normal", |
565 | "left", |
566 | "inverted", |
567 | "right" |
568 | }; |
569 | |
570 | static Rotation |
571 | xf86OutputInitialRotation(xf86OutputPtr output) |
572 | { |
573 | const char *rotate_name = xf86GetOptValString(output->options, |
574 | OPTION_ROTATE); |
575 | int i; |
576 | |
577 | if (!rotate_name) { |
578 | if (output->initial_rotation) |
579 | return output->initial_rotation; |
580 | return RR_Rotate_01; |
581 | } |
582 | |
583 | for (i = 0; i < 4; i++) |
584 | if (xf86nameCompare(direction[i], rotate_name) == 0) |
585 | return 1 << i; |
586 | return RR_Rotate_01; |
587 | } |
588 | |
589 | xf86OutputPtr |
590 | xf86OutputCreate(ScrnInfoPtr scrn, |
591 | const xf86OutputFuncsRec * funcs, const char *name) |
592 | { |
593 | xf86OutputPtr output, *outputs; |
594 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
595 | int len; |
596 | Bool primary; |
597 | |
598 | if (name) |
599 | len = strlen(name) + 1; |
600 | else |
601 | len = 0; |
602 | |
603 | output = calloc(sizeof(xf86OutputRec) + len, 1); |
604 | if (!output) |
605 | return NULL((void*)0); |
606 | output->scrn = scrn; |
607 | output->funcs = funcs; |
608 | if (name) { |
609 | output->name = (char *) (output + 1); |
610 | strcpy(output->name, name)__builtin___strcpy_chk (output->name, name, __builtin_object_size (output->name, 2 > 1 ? 1 : 0)); |
611 | } |
612 | output->subpixel_order = SubPixelUnknown0; |
613 | /* |
614 | * Use the old per-screen monitor section for the first output |
615 | */ |
616 | output->use_screen_monitor = (xf86_config->num_output == 0); |
617 | #ifdef RANDR_12_INTERFACE1 |
618 | output->randr_output = NULL((void*)0); |
619 | #endif |
620 | if (name) { |
621 | xf86OutputSetMonitor(output); |
622 | if (xf86OutputIgnored(output)) { |
623 | free(output); |
624 | return FALSE0; |
625 | } |
626 | } |
627 | |
628 | if (xf86_config->output) |
629 | outputs = reallocarrayxreallocarray(xf86_config->output, |
630 | xf86_config->num_output + 1, |
631 | sizeof(xf86OutputPtr)); |
632 | else |
633 | outputs = xallocarray(xf86_config->num_output + 1,xreallocarray(((void*)0), (xf86_config->num_output + 1), ( sizeof(xf86OutputPtr))) |
634 | sizeof(xf86OutputPtr))xreallocarray(((void*)0), (xf86_config->num_output + 1), ( sizeof(xf86OutputPtr))); |
635 | if (!outputs) { |
636 | free(output); |
637 | return NULL((void*)0); |
638 | } |
639 | |
640 | xf86_config->output = outputs; |
641 | |
642 | if (xf86GetOptValBool(output->options, OPTION_PRIMARY, &primary) && primary) { |
643 | memmove(xf86_config->output + 1, xf86_config->output,__builtin___memmove_chk (xf86_config->output + 1, xf86_config ->output, xf86_config->num_output * sizeof(xf86OutputPtr ), __builtin_object_size (xf86_config->output + 1, 0)) |
644 | xf86_config->num_output * sizeof(xf86OutputPtr))__builtin___memmove_chk (xf86_config->output + 1, xf86_config ->output, xf86_config->num_output * sizeof(xf86OutputPtr ), __builtin_object_size (xf86_config->output + 1, 0)); |
645 | xf86_config->output[0] = output; |
646 | } |
647 | else { |
648 | xf86_config->output[xf86_config->num_output] = output; |
649 | } |
650 | |
651 | xf86_config->num_output++; |
652 | |
653 | return output; |
654 | } |
655 | |
656 | Bool |
657 | xf86OutputRename(xf86OutputPtr output, const char *name) |
658 | { |
659 | char *newname = strdup(name); |
660 | |
661 | if (!newname) |
662 | return FALSE0; /* so sorry... */ |
663 | |
664 | if (output->name && output->name != (char *) (output + 1)) |
665 | free(output->name); |
666 | output->name = newname; |
667 | xf86OutputSetMonitor(output); |
668 | if (xf86OutputIgnored(output)) |
669 | return FALSE0; |
670 | return TRUE1; |
671 | } |
672 | |
673 | void |
674 | xf86OutputUseScreenMonitor(xf86OutputPtr output, Bool use_screen_monitor) |
675 | { |
676 | if (use_screen_monitor != output->use_screen_monitor) { |
677 | output->use_screen_monitor = use_screen_monitor; |
678 | xf86OutputSetMonitor(output); |
679 | } |
680 | } |
681 | |
682 | void |
683 | xf86OutputDestroy(xf86OutputPtr output) |
684 | { |
685 | ScrnInfoPtr scrn = output->scrn; |
686 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
687 | int o; |
688 | |
689 | (*output->funcs->destroy) (output); |
690 | while (output->probed_modes) |
691 | xf86DeleteMode(&output->probed_modes, output->probed_modes); |
692 | for (o = 0; o < xf86_config->num_output; o++) |
693 | if (xf86_config->output[o] == output) { |
694 | memmove(&xf86_config->output[o],__builtin___memmove_chk (&xf86_config->output[o], & xf86_config->output[o + 1], ((xf86_config->num_output - (o + 1)) * sizeof(void *)), __builtin_object_size (&xf86_config ->output[o], 0)) |
695 | &xf86_config->output[o + 1],__builtin___memmove_chk (&xf86_config->output[o], & xf86_config->output[o + 1], ((xf86_config->num_output - (o + 1)) * sizeof(void *)), __builtin_object_size (&xf86_config ->output[o], 0)) |
696 | ((xf86_config->num_output - (o + 1)) * sizeof(void *)))__builtin___memmove_chk (&xf86_config->output[o], & xf86_config->output[o + 1], ((xf86_config->num_output - (o + 1)) * sizeof(void *)), __builtin_object_size (&xf86_config ->output[o], 0)); |
697 | xf86_config->num_output--; |
698 | break; |
699 | } |
700 | if (output->name && output->name != (char *) (output + 1)) |
701 | free(output->name); |
702 | free(output); |
703 | } |
704 | |
705 | /* |
706 | * Called during CreateScreenResources to hook up RandR |
707 | */ |
708 | static Bool |
709 | xf86CrtcCreateScreenResources(ScreenPtr screen) |
710 | { |
711 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); |
712 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
713 | |
714 | screen->CreateScreenResources = config->CreateScreenResources; |
715 | |
716 | if (!(*screen->CreateScreenResources) (screen)) |
717 | return FALSE0; |
718 | |
719 | if (!xf86RandR12CreateScreenResources(screen)) |
720 | return FALSE0; |
721 | |
722 | return TRUE1; |
723 | } |
724 | |
725 | /* |
726 | * Clean up config on server reset |
727 | */ |
728 | static Bool |
729 | xf86CrtcCloseScreen(ScreenPtr screen) |
730 | { |
731 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); |
732 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
733 | int o, c; |
734 | |
735 | screen->CloseScreen = config->CloseScreen; |
736 | |
737 | xf86RotateCloseScreen(screen); |
738 | |
739 | xf86RandR12CloseScreen(screen); |
740 | |
741 | screen->CloseScreen(screen); |
742 | |
743 | for (o = 0; o < config->num_output; o++) { |
744 | xf86OutputPtr output = config->output[o]; |
745 | |
746 | output->randr_output = NULL((void*)0); |
747 | } |
748 | for (c = 0; c < config->num_crtc; c++) { |
749 | xf86CrtcPtr crtc = config->crtc[c]; |
750 | |
751 | crtc->randr_crtc = NULL((void*)0); |
752 | } |
753 | /* detach any providers */ |
754 | if (config->randr_provider) { |
755 | RRProviderDestroy(config->randr_provider); |
756 | config->randr_provider = NULL((void*)0); |
757 | } |
758 | return TRUE1; |
759 | } |
760 | |
761 | /* |
762 | * Called at ScreenInit time to set up |
763 | */ |
764 | #ifdef RANDR_13_INTERFACE1 |
765 | int |
766 | #else |
767 | Bool |
768 | #endif |
769 | xf86CrtcScreenInit(ScreenPtr screen) |
770 | { |
771 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); |
772 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
773 | int c; |
774 | |
775 | /* Rotation */ |
776 | xf86DrvMsg(scrn->scrnIndex, X_INFO, |
777 | "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); |
778 | xf86DisableRandR(); /* Disable old RandR extension support */ |
779 | xf86RandR12Init(screen); |
780 | |
781 | /* support all rotations if every crtc has the shadow alloc funcs */ |
782 | for (c = 0; c < config->num_crtc; c++) { |
783 | xf86CrtcPtr crtc = config->crtc[c]; |
784 | |
785 | if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) |
786 | break; |
787 | } |
788 | if (c == config->num_crtc) { |
789 | xf86RandR12SetRotations(screen, RR_Rotate_01 | RR_Rotate_902 | |
790 | RR_Rotate_1804 | RR_Rotate_2708 | |
791 | RR_Reflect_X16 | RR_Reflect_Y32); |
792 | xf86RandR12SetTransformSupport(screen, TRUE1); |
793 | } |
794 | else { |
795 | xf86RandR12SetRotations(screen, RR_Rotate_01); |
796 | xf86RandR12SetTransformSupport(screen, FALSE0); |
797 | } |
798 | |
799 | /* Wrap CreateScreenResources so we can initialize the RandR code */ |
800 | config->CreateScreenResources = screen->CreateScreenResources; |
801 | screen->CreateScreenResources = xf86CrtcCreateScreenResources; |
802 | |
803 | config->CloseScreen = screen->CloseScreen; |
804 | screen->CloseScreen = xf86CrtcCloseScreen; |
805 | |
806 | /* This might still be marked wrapped from a previous generation */ |
807 | config->BlockHandler = NULL((void*)0); |
808 | |
809 | #ifdef XFreeXDGA1 |
810 | _xf86_di_dga_init_internal(screen); |
811 | #endif |
812 | #ifdef RANDR_13_INTERFACE1 |
813 | return RANDR_INTERFACE_VERSION0x0104; |
814 | #else |
815 | return TRUE1; |
816 | #endif |
817 | } |
818 | |
819 | static DisplayModePtr |
820 | xf86DefaultMode(xf86OutputPtr output, int width, int height) |
821 | { |
822 | DisplayModePtr target_mode = NULL((void*)0); |
823 | DisplayModePtr mode; |
824 | int target_diff = 0; |
825 | int target_preferred = 0; |
826 | int mm_height; |
827 | |
828 | mm_height = output->mm_height; |
829 | if (!mm_height) |
830 | mm_height = (768 * 25.4) / DEFAULT_DPI96; |
831 | /* |
832 | * Pick a mode closest to DEFAULT_DPI |
833 | */ |
834 | for (mode = output->probed_modes; mode; mode = mode->next) { |
835 | int dpi; |
836 | int preferred = (((mode->type & M_T_PREFERRED0x08) != 0) + |
837 | ((mode->type & M_T_USERPREF0x80) != 0)); |
838 | int diff; |
839 | |
840 | if (xf86ModeWidth(mode, output->initial_rotation) > width || |
841 | xf86ModeHeight(mode, output->initial_rotation) > height) |
842 | continue; |
843 | |
844 | /* yes, use VDisplay here, not xf86ModeHeight */ |
845 | dpi = (mode->VDisplay * 254) / (mm_height * 10); |
846 | diff = dpi - DEFAULT_DPI96; |
847 | diff = diff < 0 ? -diff : diff; |
848 | if (target_mode == NULL((void*)0) || (preferred > target_preferred) || |
849 | (preferred == target_preferred && diff < target_diff)) { |
850 | target_mode = mode; |
851 | target_diff = diff; |
852 | target_preferred = preferred; |
853 | } |
854 | } |
855 | return target_mode; |
856 | } |
857 | |
858 | static DisplayModePtr |
859 | xf86ClosestMode(xf86OutputPtr output, |
860 | DisplayModePtr match, Rotation match_rotation, |
861 | int width, int height) |
862 | { |
863 | DisplayModePtr target_mode = NULL((void*)0); |
864 | DisplayModePtr mode; |
865 | int target_diff = 0; |
866 | |
867 | /* |
868 | * Pick a mode closest to the specified mode |
869 | */ |
870 | for (mode = output->probed_modes; mode; mode = mode->next) { |
871 | int dx, dy; |
872 | int diff; |
873 | |
874 | if (xf86ModeWidth(mode, output->initial_rotation) > width || |
875 | xf86ModeHeight(mode, output->initial_rotation) > height) |
876 | continue; |
877 | |
878 | /* exact matches are preferred */ |
879 | if (output->initial_rotation == match_rotation && |
880 | xf86ModesEqual(mode, match)) |
881 | return mode; |
882 | |
883 | dx = xf86ModeWidth(match, match_rotation) - xf86ModeWidth(mode, |
884 | output-> |
885 | initial_rotation); |
886 | dy = xf86ModeHeight(match, match_rotation) - xf86ModeHeight(mode, |
887 | output-> |
888 | initial_rotation); |
889 | diff = dx * dx + dy * dy; |
890 | if (target_mode == NULL((void*)0) || diff < target_diff) { |
891 | target_mode = mode; |
892 | target_diff = diff; |
893 | } |
894 | } |
895 | return target_mode; |
896 | } |
897 | |
898 | static DisplayModePtr |
899 | xf86OutputHasPreferredMode(xf86OutputPtr output, int width, int height) |
900 | { |
901 | DisplayModePtr mode; |
902 | |
903 | for (mode = output->probed_modes; mode; mode = mode->next) { |
904 | if (xf86ModeWidth(mode, output->initial_rotation) > width || |
905 | xf86ModeHeight(mode, output->initial_rotation) > height) |
906 | continue; |
907 | |
908 | if (mode->type & M_T_PREFERRED0x08) |
909 | return mode; |
910 | } |
911 | return NULL((void*)0); |
912 | } |
913 | |
914 | static DisplayModePtr |
915 | xf86OutputHasUserPreferredMode(xf86OutputPtr output) |
916 | { |
917 | DisplayModePtr mode, first = output->probed_modes; |
918 | |
919 | for (mode = first; mode && mode->next != first; mode = mode->next) |
920 | if (mode->type & M_T_USERPREF0x80) |
921 | return mode; |
922 | |
923 | return NULL((void*)0); |
924 | } |
925 | |
926 | static int |
927 | xf86PickCrtcs(ScrnInfoPtr scrn, |
928 | xf86CrtcPtr * best_crtcs, |
929 | DisplayModePtr * modes, int n, int width, int height) |
930 | { |
931 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
932 | int c, o; |
933 | xf86OutputPtr output; |
934 | xf86CrtcPtr crtc; |
935 | xf86CrtcPtr *crtcs; |
936 | int best_score; |
937 | int score; |
938 | int my_score; |
939 | |
940 | if (n == config->num_output) |
941 | return 0; |
942 | output = config->output[n]; |
943 | |
944 | /* |
945 | * Compute score with this output disabled |
946 | */ |
947 | best_crtcs[n] = NULL((void*)0); |
948 | best_score = xf86PickCrtcs(scrn, best_crtcs, modes, n + 1, width, height); |
949 | if (modes[n] == NULL((void*)0)) |
950 | return best_score; |
951 | |
952 | crtcs = xallocarray(config->num_output, sizeof(xf86CrtcPtr))xreallocarray(((void*)0), (config->num_output), (sizeof(xf86CrtcPtr ))); |
953 | if (!crtcs) |
954 | return best_score; |
955 | |
956 | my_score = 1; |
957 | /* Score outputs that are known to be connected higher */ |
958 | if (output->status == XF86OutputStatusConnected) |
959 | my_score++; |
960 | /* Score outputs with preferred modes higher */ |
961 | if (xf86OutputHasPreferredMode(output, width, height)) |
962 | my_score++; |
963 | /* |
964 | * Select a crtc for this output and |
965 | * then attempt to configure the remaining |
966 | * outputs |
967 | */ |
968 | for (c = 0; c < config->num_crtc; c++) { |
969 | if ((output->possible_crtcs & (1 << c)) == 0) |
970 | continue; |
971 | |
972 | crtc = config->crtc[c]; |
973 | /* |
974 | * Check to see if some other output is |
975 | * using this crtc |
976 | */ |
977 | for (o = 0; o < n; o++) |
978 | if (best_crtcs[o] == crtc) |
979 | break; |
980 | if (o < n) { |
981 | /* |
982 | * If the two outputs desire the same mode, |
983 | * see if they can be cloned |
984 | */ |
985 | if (xf86ModesEqual(modes[o], modes[n]) && |
986 | config->output[o]->initial_rotation == |
987 | config->output[n]->initial_rotation && |
988 | config->output[o]->initial_x == config->output[n]->initial_x && |
989 | config->output[o]->initial_y == config->output[n]->initial_y) { |
990 | if ((output->possible_clones & (1 << o)) == 0) |
991 | continue; /* nope, try next CRTC */ |
992 | } |
993 | else |
994 | continue; /* different modes, can't clone */ |
995 | } |
996 | crtcs[n] = crtc; |
997 | memcpy(crtcs, best_crtcs, n * sizeof(xf86CrtcPtr))__builtin___memcpy_chk (crtcs, best_crtcs, n * sizeof(xf86CrtcPtr ), __builtin_object_size (crtcs, 0)); |
998 | score = |
999 | my_score + xf86PickCrtcs(scrn, crtcs, modes, n + 1, width, height); |
1000 | if (score > best_score) { |
1001 | best_score = score; |
1002 | memcpy(best_crtcs, crtcs, config->num_output * sizeof(xf86CrtcPtr))__builtin___memcpy_chk (best_crtcs, crtcs, config->num_output * sizeof(xf86CrtcPtr), __builtin_object_size (best_crtcs, 0) ); |
1003 | } |
1004 | } |
1005 | free(crtcs); |
1006 | return best_score; |
1007 | } |
1008 | |
1009 | /* |
1010 | * Compute the virtual size necessary to place all of the available |
1011 | * crtcs in the specified configuration. |
1012 | * |
1013 | * canGrow indicates that the driver can make the screen larger than its initial |
1014 | * configuration. If FALSE, this function will enlarge the screen to include |
1015 | * the largest available mode. |
1016 | */ |
1017 | |
1018 | static void |
1019 | xf86DefaultScreenLimits(ScrnInfoPtr scrn, int *widthp, int *heightp, |
1020 | Bool canGrow) |
1021 | { |
1022 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
1023 | int width = 0, height = 0; |
1024 | int o; |
1025 | int c; |
1026 | int s; |
1027 | |
1028 | for (c = 0; c < config->num_crtc; c++) { |
1029 | int crtc_width = 0, crtc_height = 0; |
1030 | xf86CrtcPtr crtc = config->crtc[c]; |
1031 | |
1032 | if (crtc->enabled) { |
1033 | crtc_width = |
1034 | crtc->desiredX + xf86ModeWidth(&crtc->desiredMode, |
1035 | crtc->desiredRotation); |
1036 | crtc_height = |
1037 | crtc->desiredY + xf86ModeHeight(&crtc->desiredMode, |
1038 | crtc->desiredRotation); |
1039 | } |
1040 | if (!canGrow) { |
1041 | for (o = 0; o < config->num_output; o++) { |
1042 | xf86OutputPtr output = config->output[o]; |
1043 | |
1044 | for (s = 0; s < config->num_crtc; s++) |
1045 | if (output->possible_crtcs & (1 << s)) { |
1046 | DisplayModePtr mode; |
1047 | |
1048 | for (mode = output->probed_modes; mode; |
1049 | mode = mode->next) { |
1050 | if (mode->HDisplay > crtc_width) |
1051 | crtc_width = mode->HDisplay; |
1052 | if (mode->VDisplay > crtc_width) |
1053 | crtc_width = mode->VDisplay; |
1054 | if (mode->VDisplay > crtc_height) |
1055 | crtc_height = mode->VDisplay; |
1056 | if (mode->HDisplay > crtc_height) |
1057 | crtc_height = mode->HDisplay; |
1058 | } |
1059 | } |
1060 | } |
1061 | } |
1062 | if (crtc_width > width) |
1063 | width = crtc_width; |
1064 | if (crtc_height > height) |
1065 | height = crtc_height; |
1066 | } |
1067 | if (config->maxWidth && width > config->maxWidth) |
1068 | width = config->maxWidth; |
1069 | if (config->maxHeight && height > config->maxHeight) |
1070 | height = config->maxHeight; |
1071 | if (config->minWidth && width < config->minWidth) |
1072 | width = config->minWidth; |
1073 | if (config->minHeight && height < config->minHeight) |
1074 | height = config->minHeight; |
1075 | *widthp = width; |
1076 | *heightp = height; |
1077 | } |
1078 | |
1079 | #define POSITION_UNSET-100000 -100000 |
1080 | |
1081 | /* |
1082 | * check if the user configured any outputs at all |
1083 | * with either a position or a relative setting or a mode. |
1084 | */ |
1085 | static Bool |
1086 | xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr * modes) |
1087 | { |
1088 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
1089 | int o; |
1090 | Bool user_conf = FALSE0; |
1091 | |
1092 | for (o = 0; o < config->num_output; o++) { |
1093 | xf86OutputPtr output = config->output[o]; |
1094 | const char *position; |
1095 | const char *relative_name; |
1096 | OutputOpts relation; |
1097 | int r; |
1098 | |
1099 | static const OutputOpts relations[] = { |
1100 | OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF |
1101 | }; |
1102 | |
1103 | position = xf86GetOptValString(output->options, OPTION_POSITION); |
1104 | if (position) |
1105 | user_conf = TRUE1; |
1106 | |
1107 | relation = 0; |
1108 | relative_name = NULL((void*)0); |
1109 | for (r = 0; r < 4; r++) { |
1110 | relation = relations[r]; |
1111 | relative_name = xf86GetOptValString(output->options, relation); |
1112 | if (relative_name) |
1113 | break; |
1114 | } |
1115 | if (relative_name) |
1116 | user_conf = TRUE1; |
1117 | |
1118 | modes[o] = xf86OutputHasUserPreferredMode(output); |
1119 | if (modes[o]) |
1120 | user_conf = TRUE1; |
1121 | } |
1122 | |
1123 | return user_conf; |
1124 | } |
1125 | |
1126 | static Bool |
1127 | xf86InitialOutputPositions(ScrnInfoPtr scrn, DisplayModePtr * modes) |
1128 | { |
1129 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
1130 | int o; |
1131 | int min_x, min_y; |
1132 | |
1133 | /* check for initial right-of heuristic */ |
1134 | for (o = 0; o < config->num_output; o++) |
1135 | { |
1136 | xf86OutputPtr output = config->output[o]; |
1137 | |
1138 | if (output->initial_x || output->initial_y) |
1139 | return TRUE1; |
1140 | } |
1141 | |
1142 | for (o = 0; o < config->num_output; o++) { |
1143 | xf86OutputPtr output = config->output[o]; |
1144 | |
1145 | output->initial_x = output->initial_y = POSITION_UNSET-100000; |
1146 | } |
1147 | |
1148 | /* |
1149 | * Loop until all outputs are set |
1150 | */ |
1151 | for (;;) { |
1152 | Bool any_set = FALSE0; |
1153 | Bool keep_going = FALSE0; |
1154 | |
1155 | for (o = 0; o < config->num_output; o++) { |
1156 | static const OutputOpts relations[] = { |
1157 | OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF |
1158 | }; |
1159 | xf86OutputPtr output = config->output[o]; |
1160 | xf86OutputPtr relative; |
1161 | const char *relative_name; |
1162 | const char *position; |
1163 | OutputOpts relation; |
1164 | int r; |
1165 | |
1166 | if (output->initial_x != POSITION_UNSET-100000) |
1167 | continue; |
1168 | position = xf86GetOptValString(output->options, OPTION_POSITION); |
1169 | /* |
1170 | * Absolute position wins |
1171 | */ |
1172 | if (position) { |
1173 | int x, y; |
1174 | |
1175 | if (sscanf(position, "%d %d", &x, &y) == 2) { |
1176 | output->initial_x = x; |
1177 | output->initial_y = y; |
1178 | } |
1179 | else { |
1180 | xf86DrvMsg(scrn->scrnIndex, X_ERROR, |
1181 | "Output %s position not of form \"x y\"\n", |
1182 | output->name); |
1183 | output->initial_x = output->initial_y = 0; |
1184 | } |
1185 | any_set = TRUE1; |
1186 | continue; |
1187 | } |
1188 | /* |
1189 | * Next comes relative positions |
1190 | */ |
1191 | relation = 0; |
1192 | relative_name = NULL((void*)0); |
1193 | for (r = 0; r < 4; r++) { |
1194 | relation = relations[r]; |
1195 | relative_name = xf86GetOptValString(output->options, relation); |
1196 | if (relative_name) |
1197 | break; |
1198 | } |
1199 | if (relative_name) { |
1200 | int or; |
1201 | |
1202 | relative = NULL((void*)0); |
1203 | for (or = 0; or < config->num_output; or++) { |
1204 | xf86OutputPtr out_rel = config->output[or]; |
1205 | XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; |
1206 | |
1207 | if (rel_mon) { |
1208 | if (xf86nameCompare(rel_mon->mon_identifier, |
1209 | relative_name) == 0) { |
1210 | relative = config->output[or]; |
1211 | break; |
1212 | } |
1213 | } |
1214 | if (strcmp(out_rel->name, relative_name) == 0) { |
1215 | relative = config->output[or]; |
1216 | break; |
1217 | } |
1218 | } |
1219 | if (!relative) { |
1220 | xf86DrvMsg(scrn->scrnIndex, X_ERROR, |
1221 | "Cannot position output %s relative to unknown output %s\n", |
1222 | output->name, relative_name); |
1223 | output->initial_x = 0; |
1224 | output->initial_y = 0; |
1225 | any_set = TRUE1; |
1226 | continue; |
1227 | } |
1228 | if (!modes[or]) { |
1229 | xf86DrvMsg(scrn->scrnIndex, X_ERROR, |
1230 | "Cannot position output %s relative to output %s without modes\n", |
1231 | output->name, relative_name); |
1232 | output->initial_x = 0; |
1233 | output->initial_y = 0; |
1234 | any_set = TRUE1; |
1235 | continue; |
1236 | } |
1237 | if (relative->initial_x == POSITION_UNSET-100000) { |
1238 | keep_going = TRUE1; |
1239 | continue; |
1240 | } |
1241 | output->initial_x = relative->initial_x; |
1242 | output->initial_y = relative->initial_y; |
1243 | switch (relation) { |
1244 | case OPTION_BELOW: |
1245 | output->initial_y += |
1246 | xf86ModeHeight(modes[or], relative->initial_rotation); |
1247 | break; |
1248 | case OPTION_RIGHT_OF: |
1249 | output->initial_x += |
1250 | xf86ModeWidth(modes[or], relative->initial_rotation); |
1251 | break; |
1252 | case OPTION_ABOVE: |
1253 | if (modes[o]) |
1254 | output->initial_y -= |
1255 | xf86ModeHeight(modes[o], output->initial_rotation); |
1256 | break; |
1257 | case OPTION_LEFT_OF: |
1258 | if (modes[o]) |
1259 | output->initial_x -= |
1260 | xf86ModeWidth(modes[o], output->initial_rotation); |
1261 | break; |
1262 | default: |
1263 | break; |
1264 | } |
1265 | any_set = TRUE1; |
1266 | continue; |
1267 | } |
1268 | |
1269 | /* Nothing set, just stick them at 0,0 */ |
1270 | output->initial_x = 0; |
1271 | output->initial_y = 0; |
1272 | any_set = TRUE1; |
1273 | } |
1274 | if (!keep_going) |
1275 | break; |
1276 | if (!any_set) { |
1277 | for (o = 0; o < config->num_output; o++) { |
1278 | xf86OutputPtr output = config->output[o]; |
1279 | |
1280 | if (output->initial_x == POSITION_UNSET-100000) { |
1281 | xf86DrvMsg(scrn->scrnIndex, X_ERROR, |
1282 | "Output position loop. Moving %s to 0,0\n", |
1283 | output->name); |
1284 | output->initial_x = output->initial_y = 0; |
1285 | break; |
1286 | } |
1287 | } |
1288 | } |
1289 | } |
1290 | |
1291 | /* |
1292 | * normalize positions |
1293 | */ |
1294 | min_x = 1000000; |
1295 | min_y = 1000000; |
1296 | for (o = 0; o < config->num_output; o++) { |
1297 | xf86OutputPtr output = config->output[o]; |
1298 | |
1299 | if (output->initial_x < min_x) |
1300 | min_x = output->initial_x; |
1301 | if (output->initial_y < min_y) |
1302 | min_y = output->initial_y; |
1303 | } |
1304 | |
1305 | for (o = 0; o < config->num_output; o++) { |
1306 | xf86OutputPtr output = config->output[o]; |
1307 | |
1308 | output->initial_x -= min_x; |
1309 | output->initial_y -= min_y; |
1310 | } |
1311 | return TRUE1; |
1312 | } |
1313 | |
1314 | static void |
1315 | xf86InitialPanning(ScrnInfoPtr scrn) |
1316 | { |
1317 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
1318 | int o; |
1319 | |
1320 | for (o = 0; o < config->num_output; o++) { |
1321 | xf86OutputPtr output = config->output[o]; |
1322 | const char *panning = xf86GetOptValString(output->options, OPTION_PANNING); |
1323 | int width, height, left, top; |
1324 | int track_width, track_height, track_left, track_top; |
1325 | int brdr[4]; |
1326 | |
1327 | memset(&output->initialTotalArea, 0, sizeof(BoxRec))__builtin___memset_chk (&output->initialTotalArea, 0, sizeof (BoxRec), __builtin_object_size (&output->initialTotalArea , 0)); |
1328 | memset(&output->initialTrackingArea, 0, sizeof(BoxRec))__builtin___memset_chk (&output->initialTrackingArea, 0 , sizeof(BoxRec), __builtin_object_size (&output->initialTrackingArea , 0)); |
1329 | memset(output->initialBorder, 0, 4 * sizeof(INT16))__builtin___memset_chk (output->initialBorder, 0, 4 * sizeof (INT16), __builtin_object_size (output->initialBorder, 0)); |
1330 | |
1331 | if (!panning) |
1332 | continue; |
1333 | |
1334 | switch (sscanf(panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", |
1335 | &width, &height, &left, &top, |
1336 | &track_width, &track_height, &track_left, &track_top, |
1337 | &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { |
1338 | case 12: |
1339 | output->initialBorder[0] = brdr[0]; |
1340 | output->initialBorder[1] = brdr[1]; |
1341 | output->initialBorder[2] = brdr[2]; |
1342 | output->initialBorder[3] = brdr[3]; |
1343 | /* fall through */ |
1344 | case 8: |
1345 | output->initialTrackingArea.x1 = track_left; |
1346 | output->initialTrackingArea.y1 = track_top; |
1347 | output->initialTrackingArea.x2 = track_left + track_width; |
1348 | output->initialTrackingArea.y2 = track_top + track_height; |
1349 | /* fall through */ |
1350 | case 4: |
1351 | output->initialTotalArea.x1 = left; |
1352 | output->initialTotalArea.y1 = top; |
1353 | /* fall through */ |
1354 | case 2: |
1355 | output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; |
1356 | output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; |
1357 | break; |
1358 | default: |
1359 | xf86DrvMsg(scrn->scrnIndex, X_ERROR, |
1360 | "Broken panning specification '%s' for output %s in config file\n", |
1361 | panning, output->name); |
1362 | } |
1363 | } |
1364 | } |
1365 | |
1366 | /** Return - 0 + if a should be earlier, same or later than b in list |
1367 | */ |
1368 | static int |
1369 | xf86ModeCompare(DisplayModePtr a, DisplayModePtr b) |
1370 | { |
1371 | int diff; |
1372 | |
1373 | diff = ((b->type & M_T_PREFERRED0x08) != 0) - ((a->type & M_T_PREFERRED0x08) != 0); |
1374 | if (diff) |
1375 | return diff; |
1376 | diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; |
1377 | if (diff) |
1378 | return diff; |
1379 | diff = b->Clock - a->Clock; |
1380 | return diff; |
1381 | } |
1382 | |
1383 | /** |
1384 | * Insertion sort input in-place and return the resulting head |
1385 | */ |
1386 | static DisplayModePtr |
1387 | xf86SortModes(DisplayModePtr input) |
1388 | { |
1389 | DisplayModePtr output = NULL((void*)0), i, o, n, *op, prev; |
1390 | |
1391 | /* sort by preferred status and pixel area */ |
1392 | while (input) { |
1393 | i = input; |
1394 | input = input->next; |
1395 | for (op = &output; (o = *op); op = &o->next) |
1396 | if (xf86ModeCompare(o, i) > 0) |
1397 | break; |
1398 | i->next = *op; |
1399 | *op = i; |
1400 | } |
1401 | /* prune identical modes */ |
1402 | for (o = output; o && (n = o->next); o = n) { |
1403 | if (!strcmp(o->name, n->name) && xf86ModesEqual(o, n)) { |
1404 | o->next = n->next; |
1405 | free((void *) n->name); |
1406 | free(n); |
1407 | n = o; |
1408 | } |
1409 | } |
1410 | /* hook up backward links */ |
1411 | prev = NULL((void*)0); |
1412 | for (o = output; o; o = o->next) { |
1413 | o->prev = prev; |
1414 | prev = o; |
1415 | } |
1416 | return output; |
1417 | } |
1418 | |
1419 | static const char * |
1420 | preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) |
1421 | { |
1422 | const char *preferred_mode = NULL((void*)0); |
1423 | |
1424 | /* Check for a configured preference for a particular mode */ |
1425 | preferred_mode = xf86GetOptValString(output->options, |
1426 | OPTION_PREFERRED_MODE); |
1427 | if (preferred_mode) |
1428 | return preferred_mode; |
1429 | |
1430 | if (pScrn->display->modes && *pScrn->display->modes) |
1431 | preferred_mode = *pScrn->display->modes; |
1432 | |
1433 | return preferred_mode; |
1434 | } |
1435 | |
1436 | /** identify a token |
1437 | * args |
1438 | * *src a string with zero or more tokens, e.g. "tok0 tok1", |
1439 | * **token stores a pointer to the first token character, |
1440 | * *len stores the token length. |
1441 | * return |
1442 | * a pointer into src[] at the token terminating character, or |
1443 | * NULL if no token is found. |
1444 | */ |
1445 | static const char * |
1446 | gettoken(const char *src, const char **token, int *len) |
1447 | { |
1448 | const char *delim = " \t"; |
1449 | int skip; |
1450 | |
1451 | if (!src) |
1452 | return NULL((void*)0); |
1453 | |
1454 | skip = strspn(src, delim); |
1455 | *token = &src[skip]; |
1456 | |
1457 | *len = strcspn(*token, delim); |
1458 | /* Support for backslash escaped delimiters could be implemented |
1459 | * here. |
1460 | */ |
1461 | |
1462 | /* (*token)[0] != '\0' <==> *len > 0 */ |
1463 | if (*len > 0) |
1464 | return &(*token)[*len]; |
1465 | else |
1466 | return NULL((void*)0); |
1467 | } |
1468 | |
1469 | /** Check for a user configured zoom mode list, Option "ZoomModes": |
1470 | * |
1471 | * Section "Monitor" |
1472 | * Identifier "a21inch" |
1473 | * Option "ZoomModes" "1600x1200 1280x1024 1280x1024 640x480" |
1474 | * EndSection |
1475 | * |
1476 | * Each user mode name is searched for independently so the list |
1477 | * specification order is free. An output mode is matched at most |
1478 | * once, a mode with an already set M_T_USERDEF type bit is skipped. |
1479 | * Thus a repeat mode name specification matches the next output mode |
1480 | * with the same name. |
1481 | * |
1482 | * Ctrl+Alt+Keypad-{Plus,Minus} zooms {in,out} by selecting the |
1483 | * {next,previous} M_T_USERDEF mode in the screen modes list, itself |
1484 | * sorted toward lower dot area or lower dot clock frequency, see |
1485 | * modes/xf86Crtc.c: xf86SortModes() xf86SetScrnInfoModes(), and |
1486 | * common/xf86Cursor.c: xf86ZoomViewport(). |
1487 | */ |
1488 | static int |
1489 | processZoomModes(xf86OutputPtr output) |
1490 | { |
1491 | const char *zoom_modes; |
1492 | int count = 0; |
1493 | |
1494 | zoom_modes = xf86GetOptValString(output->options, OPTION_ZOOM_MODES); |
1495 | |
1496 | if (zoom_modes) { |
1497 | const char *token, *next; |
1498 | int len; |
1499 | |
1500 | next = gettoken(zoom_modes, &token, &len); |
1501 | while (next) { |
1502 | DisplayModePtr mode; |
1503 | |
1504 | for (mode = output->probed_modes; mode; mode = mode->next) |
1505 | if (!strncmp(token, mode->name, len) /* prefix match */ |
1506 | && mode->name[len] == '\0' /* equal length */ |
1507 | && !(mode->type & M_T_USERDEF0x20)) { /* no rematch */ |
1508 | mode->type |= M_T_USERDEF0x20; |
1509 | break; |
1510 | } |
1511 | |
1512 | count++; |
1513 | next = gettoken(next, &token, &len); |
1514 | } |
1515 | } |
1516 | |
1517 | return count; |
1518 | } |
1519 | |
1520 | static void |
1521 | GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) |
1522 | { |
1523 | if (!mon || !mode) |
1524 | return; |
1525 | |
1526 | mon->nHsync = 1; |
1527 | mon->hsync[0].lo = 1024.0; |
1528 | mon->hsync[0].hi = 0.0; |
1529 | |
1530 | mon->nVrefresh = 1; |
1531 | mon->vrefresh[0].lo = 1024.0; |
1532 | mon->vrefresh[0].hi = 0.0; |
1533 | |
1534 | while (mode) { |
1535 | if (!mode->HSync) |
1536 | mode->HSync = ((float) mode->Clock) / ((float) mode->HTotal); |
1537 | |
1538 | if (!mode->VRefresh) |
1539 | mode->VRefresh = (1000.0 * ((float) mode->Clock)) / |
1540 | ((float) (mode->HTotal * mode->VTotal)); |
1541 | |
1542 | if (mode->HSync < mon->hsync[0].lo) |
1543 | mon->hsync[0].lo = mode->HSync; |
1544 | |
1545 | if (mode->HSync > mon->hsync[0].hi) |
1546 | mon->hsync[0].hi = mode->HSync; |
1547 | |
1548 | if (mode->VRefresh < mon->vrefresh[0].lo) |
1549 | mon->vrefresh[0].lo = mode->VRefresh; |
1550 | |
1551 | if (mode->VRefresh > mon->vrefresh[0].hi) |
1552 | mon->vrefresh[0].hi = mode->VRefresh; |
1553 | |
1554 | mode = mode->next; |
1555 | } |
1556 | |
1557 | /* stretch out the bottom to fit 640x480@60 */ |
1558 | if (mon->hsync[0].lo > 31.0) |
1559 | mon->hsync[0].lo = 31.0; |
1560 | if (mon->vrefresh[0].lo > 58.0) |
1561 | mon->vrefresh[0].lo = 58.0; |
1562 | } |
1563 | |
1564 | enum det_monrec_source { |
1565 | sync_config, sync_edid, sync_default |
1566 | }; |
1567 | |
1568 | struct det_monrec_parameter { |
1569 | MonRec *mon_rec; |
1570 | int *max_clock; |
1571 | Bool set_hsync; |
1572 | Bool set_vrefresh; |
1573 | enum det_monrec_source *sync_source; |
1574 | }; |
1575 | |
1576 | static void |
1577 | handle_detailed_monrec(struct detailed_monitor_section *det_mon, void *data) |
1578 | { |
1579 | struct det_monrec_parameter *p; |
1580 | |
1581 | p = (struct det_monrec_parameter *) data; |
1582 | |
1583 | if (det_mon->type == DS_RANGES0xFD) { |
1584 | struct monitor_ranges *ranges = &det_mon->section.ranges; |
1585 | |
1586 | if (p->set_hsync && ranges->max_h) { |
1587 | p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; |
1588 | p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; |
1589 | p->mon_rec->nHsync++; |
1590 | if (*p->sync_source == sync_default) |
1591 | *p->sync_source = sync_edid; |
1592 | } |
1593 | if (p->set_vrefresh && ranges->max_v) { |
1594 | p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; |
1595 | p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; |
1596 | p->mon_rec->nVrefresh++; |
1597 | if (*p->sync_source == sync_default) |
1598 | *p->sync_source = sync_edid; |
1599 | } |
1600 | if (ranges->max_clock * 1000 > *p->max_clock) |
1601 | *p->max_clock = ranges->max_clock * 1000; |
1602 | } |
1603 | } |
1604 | |
1605 | void |
1606 | xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY) |
1607 | { |
1608 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
1609 | int o; |
1610 | |
1611 | /* When canGrow was TRUE in the initial configuration we have to |
1612 | * compare against the maximum values so that we don't drop modes. |
1613 | * When canGrow was FALSE, the maximum values would have been clamped |
1614 | * anyway. |
1615 | */ |
1616 | if (maxX == 0 || maxY == 0) { |
1617 | maxX = config->maxWidth; |
1618 | maxY = config->maxHeight; |
1619 | } |
1620 | |
1621 | /* Probe the list of modes for each output. */ |
1622 | for (o = 0; o < config->num_output; o++) { |
1623 | xf86OutputPtr output = config->output[o]; |
1624 | DisplayModePtr mode; |
1625 | DisplayModePtr config_modes = NULL((void*)0), output_modes, default_modes = NULL((void*)0); |
1626 | const char *preferred_mode; |
1627 | xf86MonPtr edid_monitor; |
1628 | XF86ConfMonitorPtr conf_monitor; |
1629 | MonRec mon_rec; |
1630 | int min_clock = 0; |
1631 | int max_clock = 0; |
1632 | double clock; |
1633 | Bool add_default_modes; |
1634 | Bool debug_modes = config->debug_modes || xf86Initialising; |
1635 | enum det_monrec_source sync_source = sync_default; |
1636 | |
1637 | while (output->probed_modes != NULL((void*)0)) |
1638 | xf86DeleteMode(&output->probed_modes, output->probed_modes); |
1639 | |
1640 | /* |
1641 | * Check connection status |
1642 | */ |
1643 | output->status = (*output->funcs->detect) (output); |
1644 | |
1645 | if (output->status == XF86OutputStatusDisconnected && |
1646 | !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE0)) { |
1647 | xf86OutputSetEDID(output, NULL((void*)0)); |
1648 | continue; |
1649 | } |
1650 | |
1651 | memset(&mon_rec, '\0', sizeof(mon_rec))__builtin___memset_chk (&mon_rec, '\0', sizeof(mon_rec), __builtin_object_size (&mon_rec, 0)); |
1652 | |
1653 | conf_monitor = output->conf_monitor; |
1654 | |
1655 | if (conf_monitor) { |
1656 | int i; |
1657 | |
1658 | for (i = 0; i < conf_monitor->mon_n_hsync; i++) { |
1659 | mon_rec.hsync[mon_rec.nHsync].lo = |
1660 | conf_monitor->mon_hsync[i].lo; |
1661 | mon_rec.hsync[mon_rec.nHsync].hi = |
1662 | conf_monitor->mon_hsync[i].hi; |
1663 | mon_rec.nHsync++; |
1664 | sync_source = sync_config; |
1665 | } |
1666 | for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) { |
1667 | mon_rec.vrefresh[mon_rec.nVrefresh].lo = |
1668 | conf_monitor->mon_vrefresh[i].lo; |
1669 | mon_rec.vrefresh[mon_rec.nVrefresh].hi = |
1670 | conf_monitor->mon_vrefresh[i].hi; |
1671 | mon_rec.nVrefresh++; |
1672 | sync_source = sync_config; |
1673 | } |
1674 | config_modes = xf86GetMonitorModes(scrn, conf_monitor); |
1675 | } |
1676 | |
1677 | output_modes = (*output->funcs->get_modes) (output); |
1678 | |
1679 | /* |
1680 | * If the user has a preference, respect it. |
1681 | * Otherwise, don't second-guess the driver. |
1682 | */ |
1683 | if (!xf86GetOptValBool(output->options, OPTION_DEFAULT_MODES, |
1684 | &add_default_modes)) |
1685 | add_default_modes = (output_modes == NULL((void*)0)); |
1686 | |
1687 | edid_monitor = output->MonInfo; |
1688 | |
1689 | if (edid_monitor) { |
1690 | struct det_monrec_parameter p; |
1691 | struct disp_features *features = &edid_monitor->features; |
1692 | struct cea_data_block *hdmi_db; |
1693 | |
1694 | /* if display is not continuous-frequency, don't add default modes */ |
1695 | if (!GTF_SUPPORTED(features->msc)(features->msc & 0x1)) |
1696 | add_default_modes = FALSE0; |
1697 | |
1698 | p.mon_rec = &mon_rec; |
1699 | p.max_clock = &max_clock; |
1700 | p.set_hsync = mon_rec.nHsync == 0; |
1701 | p.set_vrefresh = mon_rec.nVrefresh == 0; |
1702 | p.sync_source = &sync_source; |
1703 | |
1704 | xf86ForEachDetailedBlock(edid_monitor, handle_detailed_monrec, &p); |
1705 | |
1706 | /* Look at the CEA HDMI vendor block for the max TMDS freq */ |
1707 | hdmi_db = xf86MonitorFindHDMIBlock(edid_monitor); |
1708 | if (hdmi_db && hdmi_db->len >= 7) { |
1709 | int tmds_freq = hdmi_db->u.vendor.hdmi.max_tmds_clock * 5000; |
1710 | xf86DrvMsg(scrn->scrnIndex, X_PROBED, |
1711 | "HDMI max TMDS frequency %dKHz\n", tmds_freq); |
1712 | if (tmds_freq > max_clock) |
1713 | max_clock = tmds_freq; |
1714 | } |
1715 | } |
1716 | |
1717 | if (xf86GetOptValFreq(output->options, OPTION_MIN_CLOCK, |
1718 | OPTUNITS_KHZ, &clock)) |
1719 | min_clock = (int) clock; |
1720 | if (xf86GetOptValFreq(output->options, OPTION_MAX_CLOCK, |
1721 | OPTUNITS_KHZ, &clock)) |
1722 | max_clock = (int) clock; |
1723 | |
1724 | /* If we still don't have a sync range, guess wildly */ |
1725 | if (!mon_rec.nHsync || !mon_rec.nVrefresh) |
1726 | GuessRangeFromModes(&mon_rec, output_modes); |
1727 | |
1728 | /* |
1729 | * These limits will end up setting a 1024x768@60Hz mode by default, |
1730 | * which seems like a fairly good mode to use when nothing else is |
1731 | * specified |
1732 | */ |
1733 | if (mon_rec.nHsync == 0) { |
1734 | mon_rec.hsync[0].lo = 31.0; |
1735 | mon_rec.hsync[0].hi = 55.0; |
1736 | mon_rec.nHsync = 1; |
1737 | } |
1738 | if (mon_rec.nVrefresh == 0) { |
1739 | mon_rec.vrefresh[0].lo = 58.0; |
1740 | mon_rec.vrefresh[0].hi = 62.0; |
1741 | mon_rec.nVrefresh = 1; |
1742 | } |
1743 | |
1744 | if (add_default_modes) |
1745 | default_modes = xf86GetDefaultModes(); |
1746 | |
1747 | /* |
1748 | * If this is not an RB monitor, remove RB modes from the default |
1749 | * pool. RB modes from the config or the monitor itself are fine. |
1750 | */ |
1751 | if (!mon_rec.reducedblanking) |
1752 | xf86ValidateModesReducedBlanking(scrn, default_modes); |
1753 | |
1754 | if (sync_source == sync_config) { |
1755 | /* |
1756 | * Check output and config modes against sync range from config file |
1757 | */ |
1758 | xf86ValidateModesSync(scrn, output_modes, &mon_rec); |
1759 | xf86ValidateModesSync(scrn, config_modes, &mon_rec); |
1760 | } |
1761 | /* |
1762 | * Check default modes against sync range |
1763 | */ |
1764 | xf86ValidateModesSync(scrn, default_modes, &mon_rec); |
1765 | /* |
1766 | * Check default modes against monitor max clock |
1767 | */ |
1768 | if (max_clock) { |
1769 | xf86ValidateModesClocks(scrn, default_modes, |
1770 | &min_clock, &max_clock, 1); |
1771 | xf86ValidateModesClocks(scrn, output_modes, |
1772 | &min_clock, &max_clock, 1); |
1773 | } |
1774 | |
1775 | output->probed_modes = NULL((void*)0); |
1776 | output->probed_modes = xf86ModesAdd(output->probed_modes, config_modes); |
1777 | output->probed_modes = xf86ModesAdd(output->probed_modes, output_modes); |
1778 | output->probed_modes = |
1779 | xf86ModesAdd(output->probed_modes, default_modes); |
1780 | |
1781 | /* |
1782 | * Check all modes against max size, interlace, and doublescan |
1783 | */ |
1784 | if (maxX && maxY) |
1785 | xf86ValidateModesSize(scrn, output->probed_modes, maxX, maxY, 0); |
1786 | |
1787 | { |
1788 | int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | |
1789 | (output->doubleScanAllowed ? V_DBLSCAN : 0); |
1790 | xf86ValidateModesFlags(scrn, output->probed_modes, flags); |
1791 | } |
1792 | |
1793 | /* |
1794 | * Check all modes against output |
1795 | */ |
1796 | for (mode = output->probed_modes; mode != NULL((void*)0); mode = mode->next) |
1797 | if (mode->status == MODE_OK) |
1798 | mode->status = (*output->funcs->mode_valid) (output, mode); |
1799 | |
1800 | xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); |
1801 | |
1802 | output->probed_modes = xf86SortModes(output->probed_modes); |
1803 | |
1804 | /* Check for a configured preference for a particular mode */ |
1805 | preferred_mode = preferredMode(scrn, output); |
1806 | |
1807 | if (preferred_mode) { |
1808 | for (mode = output->probed_modes; mode; mode = mode->next) { |
1809 | if (!strcmp(preferred_mode, mode->name)) { |
1810 | if (mode != output->probed_modes) { |
1811 | if (mode->prev) |
1812 | mode->prev->next = mode->next; |
1813 | if (mode->next) |
1814 | mode->next->prev = mode->prev; |
1815 | mode->next = output->probed_modes; |
1816 | output->probed_modes->prev = mode; |
1817 | mode->prev = NULL((void*)0); |
1818 | output->probed_modes = mode; |
1819 | } |
1820 | mode->type |= (M_T_PREFERRED0x08 | M_T_USERPREF0x80); |
1821 | break; |
1822 | } |
1823 | } |
1824 | } |
1825 | |
1826 | /* Ctrl+Alt+Keypad-{Plus,Minus} zoom mode: M_T_USERDEF mode type */ |
1827 | processZoomModes(output); |
1828 | |
1829 | output->initial_rotation = xf86OutputInitialRotation(output); |
1830 | |
1831 | if (debug_modes) { |
1832 | if (output->probed_modes != NULL((void*)0)) { |
1833 | xf86DrvMsg(scrn->scrnIndex, X_INFO, |
1834 | "Printing probed modes for output %s\n", |
1835 | output->name); |
1836 | } |
1837 | else { |
1838 | xf86DrvMsg(scrn->scrnIndex, X_INFO, |
1839 | "No remaining probed modes for output %s\n", |
1840 | output->name); |
1841 | } |
1842 | } |
1843 | for (mode = output->probed_modes; mode != NULL((void*)0); mode = mode->next) { |
1844 | /* The code to choose the best mode per pipe later on will require |
1845 | * VRefresh to be set. |
1846 | */ |
1847 | mode->VRefresh = xf86ModeVRefresh(mode); |
1848 | xf86SetModeCrtc(mode, INTERLACE_HALVE_V); |
1849 | |
1850 | if (debug_modes) |
1851 | xf86PrintModeline(scrn->scrnIndex, mode); |
1852 | } |
1853 | } |
1854 | } |
1855 | |
1856 | /** |
1857 | * Copy one of the output mode lists to the ScrnInfo record |
1858 | */ |
1859 | |
1860 | static DisplayModePtr |
1861 | biggestMode(DisplayModePtr a, DisplayModePtr b) |
1862 | { |
1863 | int A, B; |
1864 | |
1865 | if (!a) |
1866 | return b; |
1867 | if (!b) |
1868 | return a; |
1869 | |
1870 | A = a->HDisplay * a->VDisplay; |
1871 | B = b->HDisplay * b->VDisplay; |
1872 | |
1873 | if (A > B) |
1874 | return a; |
1875 | |
1876 | return b; |
1877 | } |
1878 | |
1879 | static xf86OutputPtr |
1880 | SetCompatOutput(xf86CrtcConfigPtr config) |
1881 | { |
1882 | xf86OutputPtr output = NULL((void*)0), test = NULL((void*)0); |
1883 | DisplayModePtr maxmode = NULL((void*)0), testmode, mode; |
1884 | int o, compat = -1, count, mincount = 0; |
1885 | |
1886 | if (config->num_output == 0) |
1887 | return NULL((void*)0); |
1888 | |
1889 | /* Look for one that's definitely connected */ |
1890 | for (o = 0; o < config->num_output; o++) { |
1891 | test = config->output[o]; |
1892 | if (!test->crtc) |
1893 | continue; |
1894 | if (test->status != XF86OutputStatusConnected) |
1895 | continue; |
1896 | if (!test->probed_modes) |
1897 | continue; |
1898 | |
1899 | testmode = mode = test->probed_modes; |
1900 | for (count = 0; mode; mode = mode->next, count++) |
1901 | testmode = biggestMode(testmode, mode); |
1902 | |
1903 | if (!output) { |
1904 | output = test; |
1905 | compat = o; |
1906 | maxmode = testmode; |
1907 | mincount = count; |
1908 | } |
1909 | else if (maxmode == biggestMode(maxmode, testmode)) { |
1910 | output = test; |
1911 | compat = o; |
1912 | maxmode = testmode; |
1913 | mincount = count; |
1914 | } |
1915 | else if ((maxmode->HDisplay == testmode->HDisplay) && |
1916 | (maxmode->VDisplay == testmode->VDisplay) && |
1917 | count <= mincount) { |
1918 | output = test; |
1919 | compat = o; |
1920 | maxmode = testmode; |
1921 | mincount = count; |
1922 | } |
1923 | } |
1924 | |
1925 | /* If we didn't find one, take anything we can get */ |
1926 | if (!output) { |
1927 | for (o = 0; o < config->num_output; o++) { |
1928 | test = config->output[o]; |
1929 | if (!test->crtc) |
1930 | continue; |
1931 | if (!test->probed_modes) |
1932 | continue; |
1933 | |
1934 | if (!output) { |
1935 | output = test; |
1936 | compat = o; |
1937 | } |
1938 | else if (test->probed_modes->HDisplay < |
1939 | output->probed_modes->HDisplay) { |
1940 | output = test; |
1941 | compat = o; |
1942 | } |
1943 | } |
1944 | } |
1945 | |
1946 | if (compat >= 0) { |
1947 | config->compat_output = compat; |
1948 | } |
1949 | else if (config->compat_output >= 0 && config->compat_output < config->num_output) { |
1950 | /* Don't change the compat output when no valid outputs found */ |
1951 | output = config->output[config->compat_output]; |
1952 | } |
1953 | |
1954 | /* All outputs are disconnected, select one to fake */ |
1955 | if (!output && config->num_output) { |
1956 | config->compat_output = 0; |
1957 | output = config->output[config->compat_output]; |
1958 | } |
1959 | |
1960 | return output; |
1961 | } |
1962 | |
1963 | void |
1964 | xf86SetScrnInfoModes(ScrnInfoPtr scrn) |
1965 | { |
1966 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
1967 | xf86OutputPtr output; |
1968 | xf86CrtcPtr crtc; |
1969 | DisplayModePtr last, mode = NULL((void*)0); |
1970 | |
1971 | output = SetCompatOutput(config); |
1972 | |
1973 | if (!output) |
1974 | return; /* punt */ |
1975 | |
1976 | crtc = output->crtc; |
1977 | |
1978 | /* Clear any existing modes from scrn->modes */ |
1979 | while (scrn->modes != NULL((void*)0)) |
1980 | xf86DeleteMode(&scrn->modes, scrn->modes); |
1981 | |
1982 | /* Set scrn->modes to the mode list for the 'compat' output */ |
1983 | scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); |
1984 | |
1985 | if (crtc) { |
1986 | for (mode = scrn->modes; mode; mode = mode->next) |
1987 | if (xf86ModesEqual(mode, &crtc->desiredMode)) |
1988 | break; |
1989 | } |
1990 | |
1991 | if (!scrn->modes) { |
1992 | scrn->modes = xf86ModesAdd(scrn->modes, |
1993 | xf86CVTMode(scrn->display->virtualX, |
1994 | scrn->display->virtualY, |
1995 | 60, 0, 0)); |
1996 | } |
1997 | |
1998 | /* For some reason, scrn->modes is circular, unlike the other mode |
1999 | * lists. How great is that? |
2000 | */ |
2001 | for (last = scrn->modes; last && last->next; last = last->next); |
2002 | last->next = scrn->modes; |
2003 | scrn->modes->prev = last; |
2004 | if (mode) { |
2005 | while (scrn->modes != mode) |
2006 | scrn->modes = scrn->modes->next; |
2007 | } |
2008 | |
2009 | scrn->currentMode = scrn->modes; |
2010 | #ifdef XFreeXDGA1 |
2011 | if (scrn->pScreen) |
2012 | _xf86_di_dga_reinit_internal(scrn->pScreen); |
2013 | #endif |
2014 | } |
2015 | |
2016 | static Bool |
2017 | xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, |
2018 | Bool *enabled) |
2019 | { |
2020 | Bool any_enabled = FALSE0; |
2021 | int o; |
2022 | |
2023 | /* |
2024 | * Don't bother enabling outputs on GPU screens: a client needs to attach |
2025 | * it to a source provider before setting a mode that scans out a shared |
2026 | * pixmap. |
2027 | */ |
2028 | if (scrn->is_gpu) |
2029 | return FALSE0; |
2030 | |
2031 | for (o = 0; o < config->num_output; o++) |
2032 | any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE1); |
2033 | |
2034 | if (!any_enabled) { |
2035 | xf86DrvMsg(scrn->scrnIndex, X_WARNING, |
2036 | "No outputs definitely connected, trying again...\n"); |
2037 | |
2038 | for (o = 0; o < config->num_output; o++) |
2039 | any_enabled |= enabled[o] = |
2040 | xf86OutputEnabled(config->output[o], FALSE0); |
2041 | } |
2042 | |
2043 | return any_enabled; |
2044 | } |
2045 | |
2046 | static Bool |
2047 | nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) |
2048 | { |
2049 | int o = *index; |
2050 | |
2051 | for (o++; o < config->num_output; o++) { |
2052 | if (enabled[o]) { |
2053 | *index = o; |
2054 | return TRUE1; |
2055 | } |
2056 | } |
2057 | |
2058 | return FALSE0; |
2059 | } |
2060 | |
2061 | static Bool |
2062 | aspectMatch(float a, float b) |
2063 | { |
2064 | return fabs(1 - (a / b)) < 0.05; |
2065 | } |
2066 | |
2067 | static DisplayModePtr |
2068 | nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) |
2069 | { |
2070 | DisplayModePtr m = NULL((void*)0); |
2071 | |
2072 | if (!o) |
2073 | return NULL((void*)0); |
2074 | |
2075 | if (!last) |
2076 | m = o->probed_modes; |
2077 | else |
2078 | m = last->next; |
2079 | |
2080 | for (; m; m = m->next) |
2081 | if (aspectMatch(aspect, (float) m->HDisplay / (float) m->VDisplay)) |
2082 | return m; |
2083 | |
2084 | return NULL((void*)0); |
2085 | } |
2086 | |
2087 | static DisplayModePtr |
2088 | bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) |
2089 | { |
2090 | int o = -1, p; |
2091 | DisplayModePtr mode = NULL((void*)0), test = NULL((void*)0), match = NULL((void*)0); |
2092 | |
2093 | if (!nextEnabledOutput(config, enabled, &o)) |
2094 | return NULL((void*)0); |
2095 | while ((mode = nextAspectMode(config->output[o], mode, aspect))) { |
2096 | test = mode; |
2097 | for (p = o; nextEnabledOutput(config, enabled, &p);) { |
2098 | test = xf86OutputFindClosestMode(config->output[p], mode); |
2099 | if (!test) |
2100 | break; |
2101 | if (test->HDisplay != mode->HDisplay || |
2102 | test->VDisplay != mode->VDisplay) { |
2103 | test = NULL((void*)0); |
2104 | break; |
2105 | } |
2106 | } |
2107 | |
2108 | /* if we didn't match it on all outputs, try the next one */ |
2109 | if (!test) |
2110 | continue; |
2111 | |
2112 | /* if it's bigger than the last one, save it */ |
2113 | if (!match || (test->HDisplay > match->HDisplay)) |
2114 | match = test; |
2115 | } |
2116 | |
2117 | /* return the biggest one found */ |
2118 | return match; |
2119 | } |
2120 | |
2121 | static int |
2122 | numEnabledOutputs(xf86CrtcConfigPtr config, Bool *enabled) |
2123 | { |
2124 | int i = 0, p; |
2125 | |
2126 | for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; |
2127 | |
2128 | return i; |
2129 | } |
2130 | |
2131 | static Bool |
2132 | xf86TargetRightOf(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, |
2133 | DisplayModePtr *modes, Bool *enabled, |
2134 | int width, int height) |
2135 | { |
2136 | int o; |
2137 | int w = 0; |
2138 | Bool has_tile = FALSE0; |
2139 | uint32_t configured_outputs; |
2140 | |
2141 | if (scrn->preferClone) |
2142 | return FALSE0; |
2143 | |
2144 | if (numEnabledOutputs(config, enabled) < 2) |
2145 | return FALSE0; |
2146 | |
2147 | for (o = -1; nextEnabledOutput(config, enabled, &o); ) { |
2148 | DisplayModePtr mode = |
2149 | xf86OutputHasPreferredMode(config->output[o], width, height); |
2150 | |
2151 | if (!mode) |
2152 | return FALSE0; |
2153 | |
2154 | w += mode->HDisplay; |
2155 | } |
2156 | |
2157 | if (w > width) |
2158 | return FALSE0; |
2159 | |
2160 | w = 0; |
2161 | configured_outputs = 0; |
2162 | |
2163 | for (o = -1; nextEnabledOutput(config, enabled, &o); ) { |
2164 | DisplayModePtr mode = |
2165 | xf86OutputHasPreferredMode(config->output[o], width, height); |
2166 | |
2167 | if (configured_outputs & (1 << o)) |
2168 | continue; |
2169 | |
2170 | if (config->output[o]->tile_info.group_id) { |
2171 | has_tile = TRUE1; |
2172 | continue; |
2173 | } |
2174 | |
2175 | config->output[o]->initial_x = w; |
2176 | w += mode->HDisplay; |
2177 | |
2178 | configured_outputs |= (1 << o); |
2179 | modes[o] = mode; |
2180 | } |
2181 | |
2182 | if (has_tile) { |
2183 | for (o = -1; nextEnabledOutput(config, enabled, &o); ) { |
2184 | int ht, vt, ot; |
2185 | int add_x, cur_x = w; |
2186 | struct xf86CrtcTileInfo *tile_info = &config->output[o]->tile_info, *this_tile; |
2187 | if (configured_outputs & (1 << o)) |
2188 | continue; |
2189 | if (!tile_info->group_id) |
2190 | continue; |
2191 | |
2192 | if (tile_info->tile_h_loc != 0 && tile_info->tile_v_loc != 0) |
2193 | continue; |
2194 | |
2195 | for (ht = 0; ht < tile_info->num_h_tile; ht++) { |
2196 | int cur_y = 0; |
2197 | add_x = 0; |
2198 | for (vt = 0; vt < tile_info->num_v_tile; vt++) { |
2199 | |
2200 | for (ot = -1; nextEnabledOutput(config, enabled, &ot); ) { |
2201 | |
2202 | DisplayModePtr mode = |
2203 | xf86OutputHasPreferredMode(config->output[ot], width, height); |
2204 | if (!config->output[ot]->tile_info.group_id) |
2205 | continue; |
2206 | |
2207 | this_tile = &config->output[ot]->tile_info; |
2208 | if (this_tile->group_id != tile_info->group_id) |
2209 | continue; |
2210 | |
2211 | if (this_tile->tile_h_loc != ht || |
2212 | this_tile->tile_v_loc != vt) |
2213 | continue; |
2214 | |
2215 | config->output[ot]->initial_x = cur_x; |
2216 | config->output[ot]->initial_y = cur_y; |
2217 | |
2218 | if (vt == 0) |
2219 | add_x = this_tile->tile_h_size; |
2220 | cur_y += this_tile->tile_v_size; |
2221 | configured_outputs |= (1 << ot); |
2222 | modes[ot] = mode; |
2223 | } |
2224 | } |
2225 | cur_x += add_x; |
2226 | } |
2227 | w = cur_x; |
2228 | } |
2229 | } |
2230 | return TRUE1; |
2231 | } |
2232 | |
2233 | static Bool |
2234 | xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, |
2235 | DisplayModePtr * modes, Bool *enabled, |
2236 | int width, int height) |
2237 | { |
2238 | int o, p; |
2239 | int max_pref_width = 0, max_pref_height = 0; |
2240 | DisplayModePtr *preferred, *preferred_match; |
2241 | Bool ret = FALSE0; |
2242 | |
2243 | preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr))XNFcallocarray((config->num_output), (sizeof(DisplayModePtr ))); |
2244 | preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr))XNFcallocarray((config->num_output), (sizeof(DisplayModePtr ))); |
2245 | |
2246 | /* Check if the preferred mode is available on all outputs */ |
2247 | for (p = -1; nextEnabledOutput(config, enabled, &p);) { |
2248 | Rotation r = config->output[p]->initial_rotation; |
2249 | DisplayModePtr mode; |
2250 | |
2251 | if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], |
2252 | width, height))) { |
2253 | int pref_width = xf86ModeWidth(preferred[p], r); |
2254 | int pref_height = xf86ModeHeight(preferred[p], r); |
2255 | Bool all_match = TRUE1; |
2256 | |
2257 | for (o = -1; nextEnabledOutput(config, enabled, &o);) { |
2258 | Bool match = FALSE0; |
2259 | xf86OutputPtr output = config->output[o]; |
2260 | |
2261 | if (o == p) |
2262 | continue; |
2263 | |
2264 | /* |
2265 | * First see if the preferred mode matches on the next |
2266 | * output as well. This catches the common case of identical |
2267 | * monitors and makes sure they all have the same timings |
2268 | * and refresh. If that fails, we fall back to trying to |
2269 | * match just width & height. |
2270 | */ |
2271 | mode = xf86OutputHasPreferredMode(output, pref_width, |
2272 | pref_height); |
2273 | if (mode && xf86ModesEqual(mode, preferred[p])) { |
2274 | preferred[o] = mode; |
2275 | match = TRUE1; |
2276 | } |
2277 | else { |
2278 | for (mode = output->probed_modes; mode; mode = mode->next) { |
2279 | Rotation ir = output->initial_rotation; |
2280 | |
2281 | if (xf86ModeWidth(mode, ir) == pref_width && |
2282 | xf86ModeHeight(mode, ir) == pref_height) { |
2283 | preferred[o] = mode; |
2284 | match = TRUE1; |
2285 | } |
2286 | } |
2287 | } |
2288 | |
2289 | all_match &= match; |
2290 | } |
2291 | |
2292 | if (all_match && |
2293 | (pref_width * pref_height > max_pref_width * max_pref_height)) { |
2294 | for (o = -1; nextEnabledOutput(config, enabled, &o);) |
2295 | preferred_match[o] = preferred[o]; |
2296 | max_pref_width = pref_width; |
2297 | max_pref_height = pref_height; |
2298 | ret = TRUE1; |
2299 | } |
2300 | } |
2301 | } |
2302 | |
2303 | /* |
2304 | * If there's no preferred mode, but only one monitor, pick the |
2305 | * biggest mode for its aspect ratio or 4:3, assuming one exists. |
2306 | */ |
2307 | if (!ret) |
2308 | do { |
2309 | float aspect = 0.0; |
2310 | DisplayModePtr a = NULL((void*)0), b = NULL((void*)0); |
2311 | |
2312 | if (numEnabledOutputs(config, enabled) != 1) |
2313 | break; |
2314 | |
2315 | p = -1; |
2316 | nextEnabledOutput(config, enabled, &p); |
2317 | if (config->output[p]->mm_height) |
2318 | aspect = (float) config->output[p]->mm_width / |
2319 | (float) config->output[p]->mm_height; |
2320 | |
2321 | a = bestModeForAspect(config, enabled, 4.0/3.0); |
2322 | if (aspect) |
2323 | b = bestModeForAspect(config, enabled, aspect); |
2324 | |
2325 | preferred_match[p] = biggestMode(a, b); |
2326 | |
2327 | if (preferred_match[p]) |
2328 | ret = TRUE1; |
2329 | |
2330 | } while (0); |
2331 | |
2332 | if (ret) { |
2333 | /* oh good, there is a match. stash the selected modes and return. */ |
2334 | memcpy(modes, preferred_match,__builtin___memcpy_chk (modes, preferred_match, config->num_output * sizeof(DisplayModePtr), __builtin_object_size (modes, 0)) |
2335 | config->num_output * sizeof(DisplayModePtr))__builtin___memcpy_chk (modes, preferred_match, config->num_output * sizeof(DisplayModePtr), __builtin_object_size (modes, 0)); |
2336 | } |
2337 | |
2338 | free(preferred); |
2339 | free(preferred_match); |
2340 | return ret; |
2341 | } |
2342 | |
2343 | static Bool |
2344 | xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, |
2345 | DisplayModePtr * modes, Bool *enabled, int width, int height) |
2346 | { |
2347 | int o; |
2348 | float aspect = 0.0, *aspects; |
2349 | xf86OutputPtr output; |
2350 | Bool ret = FALSE0; |
2351 | DisplayModePtr guess = NULL((void*)0), aspect_guess = NULL((void*)0), base_guess = NULL((void*)0); |
2352 | |
2353 | aspects = xnfcalloc(config->num_output, sizeof(float))XNFcallocarray((config->num_output), (sizeof(float))); |
2354 | |
2355 | /* collect the aspect ratios */ |
2356 | for (o = -1; nextEnabledOutput(config, enabled, &o);) { |
2357 | output = config->output[o]; |
2358 | if (output->mm_height) |
2359 | aspects[o] = (float) output->mm_width / (float) output->mm_height; |
2360 | else |
2361 | aspects[o] = 4.0 / 3.0; |
2362 | } |
2363 | |
2364 | /* check that they're all the same */ |
2365 | for (o = -1; nextEnabledOutput(config, enabled, &o);) { |
2366 | output = config->output[o]; |
Value stored to 'output' is never read | |
2367 | if (!aspect) { |
2368 | aspect = aspects[o]; |
2369 | } |
2370 | else if (!aspectMatch(aspect, aspects[o])) { |
2371 | goto no_aspect_match; |
2372 | } |
2373 | } |
2374 | |
2375 | /* if they're all 4:3, just skip ahead and save effort */ |
2376 | if (!aspectMatch(aspect, 4.0 / 3.0)) |
2377 | aspect_guess = bestModeForAspect(config, enabled, aspect); |
2378 | |
2379 | no_aspect_match: |
2380 | base_guess = bestModeForAspect(config, enabled, 4.0 / 3.0); |
2381 | |
2382 | guess = biggestMode(base_guess, aspect_guess); |
2383 | |
2384 | if (!guess) |
2385 | goto out; |
2386 | |
2387 | /* found a mode that works everywhere, now apply it */ |
2388 | for (o = -1; nextEnabledOutput(config, enabled, &o);) { |
2389 | modes[o] = xf86OutputFindClosestMode(config->output[o], guess); |
2390 | } |
2391 | ret = TRUE1; |
2392 | |
2393 | out: |
2394 | free(aspects); |
2395 | return ret; |
2396 | } |
2397 | |
2398 | static Bool |
2399 | xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, |
2400 | DisplayModePtr * modes, Bool *enabled, int width, int height) |
2401 | { |
2402 | DisplayModePtr target_mode = NULL((void*)0); |
2403 | Rotation target_rotation = RR_Rotate_01; |
2404 | DisplayModePtr default_mode; |
2405 | int default_preferred, target_preferred = 0, o; |
2406 | |
2407 | /* User preferred > preferred > other modes */ |
2408 | for (o = -1; nextEnabledOutput(config, enabled, &o);) { |
2409 | default_mode = xf86DefaultMode(config->output[o], width, height); |
2410 | if (!default_mode) |
2411 | continue; |
2412 | |
2413 | default_preferred = (((default_mode->type & M_T_PREFERRED0x08) != 0) + |
2414 | ((default_mode->type & M_T_USERPREF0x80) != 0)); |
2415 | |
2416 | if (default_preferred > target_preferred || !target_mode) { |
2417 | target_mode = default_mode; |
2418 | target_preferred = default_preferred; |
2419 | target_rotation = config->output[o]->initial_rotation; |
2420 | config->compat_output = o; |
2421 | } |
2422 | } |
2423 | |
2424 | if (target_mode) |
2425 | modes[config->compat_output] = target_mode; |
2426 | |
2427 | /* Fill in other output modes */ |
2428 | for (o = -1; nextEnabledOutput(config, enabled, &o);) { |
2429 | if (!modes[o]) |
2430 | modes[o] = xf86ClosestMode(config->output[o], target_mode, |
2431 | target_rotation, width, height); |
2432 | } |
2433 | |
2434 | return target_mode != NULL((void*)0); |
2435 | } |
2436 | |
2437 | static Bool |
2438 | xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, |
2439 | DisplayModePtr * modes, Bool *enabled, int width, int height) |
2440 | { |
2441 | int o; |
2442 | |
2443 | if (xf86UserConfiguredOutputs(scrn, modes)) |
2444 | return xf86TargetFallback(scrn, config, modes, enabled, width, height); |
2445 | |
2446 | for (o = -1; nextEnabledOutput(config, enabled, &o);) |
2447 | if (xf86OutputHasUserPreferredMode(config->output[o])) |
2448 | return |
2449 | xf86TargetFallback(scrn, config, modes, enabled, width, height); |
2450 | |
2451 | return FALSE0; |
2452 | } |
2453 | |
2454 | static Bool |
2455 | xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, |
2456 | float gamma_blue) |
2457 | { |
2458 | int i, size = 256; |
2459 | CARD16 *red, *green, *blue; |
2460 | |
2461 | red = xallocarray(size, 3 * sizeof(CARD16))xreallocarray(((void*)0), (size), (3 * sizeof(CARD16))); |
2462 | green = red + size; |
2463 | blue = green + size; |
2464 | |
2465 | /* Only cause warning if user wanted gamma to be set. */ |
2466 | if (!crtc->funcs->gamma_set && |
2467 | (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { |
2468 | free(red); |
2469 | return FALSE0; |
2470 | } |
2471 | else if (!crtc->funcs->gamma_set) { |
2472 | free(red); |
2473 | return TRUE1; |
2474 | } |
2475 | |
2476 | /* At this early stage none of the randr-interface stuff is up. |
2477 | * So take the default gamma size for lack of something better. |
2478 | */ |
2479 | for (i = 0; i < size; i++) { |
2480 | if (gamma_red == 1.0) |
2481 | red[i] = i << 8; |
2482 | else |
2483 | red[i] = (CARD16) (pow((double) i / (double) (size - 1), |
2484 | 1. / (double) gamma_red) * (double) (size - |
2485 | 1) * |
2486 | 256); |
2487 | |
2488 | if (gamma_green == 1.0) |
2489 | green[i] = i << 8; |
2490 | else |
2491 | green[i] = (CARD16) (pow((double) i / (double) (size - 1), |
2492 | 1. / (double) gamma_green) * |
2493 | (double) (size - 1) * 256); |
2494 | |
2495 | if (gamma_blue == 1.0) |
2496 | blue[i] = i << 8; |
2497 | else |
2498 | blue[i] = (CARD16) (pow((double) i / (double) (size - 1), |
2499 | 1. / (double) gamma_blue) * (double) (size - |
2500 | 1) * |
2501 | 256); |
2502 | } |
2503 | |
2504 | /* Default size is 256, so anything else is failure. */ |
2505 | if (size != crtc->gamma_size) { |
2506 | free(red); |
2507 | return FALSE0; |
2508 | } |
2509 | |
2510 | crtc->gamma_size = size; |
2511 | memcpy(crtc->gamma_red, red, crtc->gamma_size * sizeof(CARD16))__builtin___memcpy_chk (crtc->gamma_red, red, crtc->gamma_size * sizeof(CARD16), __builtin_object_size (crtc->gamma_red, 0)); |
2512 | memcpy(crtc->gamma_green, green, crtc->gamma_size * sizeof(CARD16))__builtin___memcpy_chk (crtc->gamma_green, green, crtc-> gamma_size * sizeof(CARD16), __builtin_object_size (crtc-> gamma_green, 0)); |
2513 | memcpy(crtc->gamma_blue, blue, crtc->gamma_size * sizeof(CARD16))__builtin___memcpy_chk (crtc->gamma_blue, blue, crtc->gamma_size * sizeof(CARD16), __builtin_object_size (crtc->gamma_blue , 0)); |
2514 | |
2515 | /* Do not set gamma now, delay until the crtc is activated. */ |
2516 | |
2517 | free(red); |
2518 | |
2519 | return TRUE1; |
2520 | } |
2521 | |
2522 | static Bool |
2523 | xf86OutputSetInitialGamma(xf86OutputPtr output) |
2524 | { |
2525 | XF86ConfMonitorPtr mon = output->conf_monitor; |
2526 | float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; |
2527 | |
2528 | if (!mon) |
2529 | return TRUE1; |
2530 | |
2531 | if (!output->crtc) |
2532 | return FALSE0; |
2533 | |
2534 | /* Get configured values, where they exist. */ |
2535 | if (mon->mon_gamma_red >= GAMMA_MIN(1.0 / 10.0) && mon->mon_gamma_red <= GAMMA_MAX10.0) |
2536 | gamma_red = mon->mon_gamma_red; |
2537 | |
2538 | if (mon->mon_gamma_green >= GAMMA_MIN(1.0 / 10.0) && mon->mon_gamma_green <= GAMMA_MAX10.0) |
2539 | gamma_green = mon->mon_gamma_green; |
2540 | |
2541 | if (mon->mon_gamma_blue >= GAMMA_MIN(1.0 / 10.0) && mon->mon_gamma_blue <= GAMMA_MAX10.0) |
2542 | gamma_blue = mon->mon_gamma_blue; |
2543 | |
2544 | /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ |
2545 | if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { |
2546 | xf86DrvMsg(output->scrn->scrnIndex, X_INFO, |
2547 | "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", |
2548 | output->name, gamma_red, gamma_green, gamma_blue); |
2549 | return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, |
2550 | gamma_blue); |
2551 | } |
2552 | else |
2553 | return TRUE1; |
2554 | } |
2555 | |
2556 | /** |
2557 | * Construct default screen configuration |
2558 | * |
2559 | * Given auto-detected (and, eventually, configured) values, |
2560 | * construct a usable configuration for the system |
2561 | * |
2562 | * canGrow indicates that the driver can resize the screen to larger than its |
2563 | * initially configured size via the config->funcs->resize hook. If TRUE, this |
2564 | * function will set virtualX and virtualY to match the initial configuration |
2565 | * and leave config->max{Width,Height} alone. If FALSE, it will bloat |
2566 | * virtual[XY] to include the largest modes and set config->max{Width,Height} |
2567 | * accordingly. |
2568 | */ |
2569 | |
2570 | Bool |
2571 | xf86InitialConfiguration(ScrnInfoPtr scrn, Bool canGrow) |
2572 | { |
2573 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
2574 | int o, c; |
2575 | xf86CrtcPtr *crtcs; |
2576 | DisplayModePtr *modes; |
2577 | Bool *enabled; |
2578 | int width, height; |
2579 | int i = scrn->scrnIndex; |
2580 | Bool have_outputs = TRUE1; |
2581 | Bool ret; |
2582 | Bool success = FALSE0; |
2583 | |
2584 | /* Set up the device options */ |
2585 | config->options = xnfalloc(sizeof(xf86DeviceOptions))XNFalloc((unsigned long)(sizeof(xf86DeviceOptions))); |
2586 | memcpy(config->options, xf86DeviceOptions, sizeof(xf86DeviceOptions))__builtin___memcpy_chk (config->options, xf86DeviceOptions , sizeof(xf86DeviceOptions), __builtin_object_size (config-> options, 0)); |
2587 | xf86ProcessOptions(scrn->scrnIndex, scrn->options, config->options); |
2588 | config->debug_modes = xf86ReturnOptValBool(config->options, |
2589 | OPTION_MODEDEBUG, FALSE0); |
2590 | |
2591 | if (scrn->display->virtualX && !scrn->is_gpu) |
2592 | width = scrn->display->virtualX; |
2593 | else |
2594 | width = config->maxWidth; |
2595 | if (scrn->display->virtualY && !scrn->is_gpu) |
2596 | height = scrn->display->virtualY; |
2597 | else |
2598 | height = config->maxHeight; |
2599 | |
2600 | xf86ProbeOutputModes(scrn, width, height); |
2601 | |
2602 | crtcs = xnfcalloc(config->num_output, sizeof(xf86CrtcPtr))XNFcallocarray((config->num_output), (sizeof(xf86CrtcPtr)) ); |
2603 | modes = xnfcalloc(config->num_output, sizeof(DisplayModePtr))XNFcallocarray((config->num_output), (sizeof(DisplayModePtr ))); |
2604 | enabled = xnfcalloc(config->num_output, sizeof(Bool))XNFcallocarray((config->num_output), (sizeof(Bool))); |
2605 | |
2606 | ret = xf86CollectEnabledOutputs(scrn, config, enabled); |
2607 | if (ret == FALSE0 && canGrow) { |
2608 | if (!scrn->is_gpu) |
2609 | xf86DrvMsg(i, X_WARNING, |
2610 | "Unable to find connected outputs - setting %dx%d " |
2611 | "initial framebuffer\n", |
2612 | NO_OUTPUT_DEFAULT_WIDTH1024, NO_OUTPUT_DEFAULT_HEIGHT768); |
2613 | have_outputs = FALSE0; |
2614 | } |
2615 | else { |
2616 | if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) |
2617 | xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); |
2618 | else if (xf86TargetRightOf(scrn, config, modes, enabled, width, height)) |
2619 | xf86DrvMsg(i, X_INFO, "Using spanning desktop for initial modes\n"); |
2620 | else if (xf86TargetPreferred |
2621 | (scrn, config, modes, enabled, width, height)) |
2622 | xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); |
2623 | else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) |
2624 | xf86DrvMsg(i, X_INFO, |
2625 | "Using fuzzy aspect match for initial modes\n"); |
2626 | else if (xf86TargetFallback |
2627 | (scrn, config, modes, enabled, width, height)) |
2628 | xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); |
2629 | else |
2630 | xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); |
2631 | } |
2632 | |
2633 | for (o = -1; nextEnabledOutput(config, enabled, &o);) { |
2634 | if (!modes[o]) |
2635 | xf86DrvMsg(scrn->scrnIndex, X_ERROR, |
2636 | "Output %s enabled but has no modes\n", |
2637 | config->output[o]->name); |
2638 | else |
2639 | xf86DrvMsg (scrn->scrnIndex, X_INFO, |
2640 | "Output %s using initial mode %s +%d+%d\n", |
2641 | config->output[o]->name, modes[o]->name, |
2642 | config->output[o]->initial_x, |
2643 | config->output[o]->initial_y); |
2644 | } |
2645 | |
2646 | /* |
2647 | * Set the position of each output |
2648 | */ |
2649 | if (!xf86InitialOutputPositions(scrn, modes)) |
2650 | goto bailout; |
2651 | |
2652 | /* |
2653 | * Set initial panning of each output |
2654 | */ |
2655 | xf86InitialPanning(scrn); |
2656 | |
2657 | /* |
2658 | * Assign CRTCs to fit output configuration |
2659 | */ |
2660 | if (have_outputs && !xf86PickCrtcs(scrn, crtcs, modes, 0, width, height)) |
2661 | goto bailout; |
2662 | |
2663 | /* XXX override xf86 common frame computation code */ |
2664 | |
2665 | if (!scrn->is_gpu) { |
2666 | scrn->display->frameX0 = 0; |
2667 | scrn->display->frameY0 = 0; |
2668 | } |
2669 | |
2670 | for (c = 0; c < config->num_crtc; c++) { |
2671 | xf86CrtcPtr crtc = config->crtc[c]; |
2672 | |
2673 | crtc->enabled = FALSE0; |
2674 | memset(&crtc->desiredMode, '\0', sizeof(crtc->desiredMode))__builtin___memset_chk (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode), __builtin_object_size (&crtc-> desiredMode, 0)); |
2675 | /* Set default gamma for all crtc's. */ |
2676 | /* This is done to avoid problems later on with cloned outputs. */ |
2677 | xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); |
2678 | } |
2679 | |
2680 | if (xf86_crtc_supports_gamma(scrn)) |
2681 | xf86DrvMsg(scrn->scrnIndex, X_INFO, |
2682 | "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); |
2683 | |
2684 | /* |
2685 | * Set initial configuration |
2686 | */ |
2687 | for (o = 0; o < config->num_output; o++) { |
2688 | xf86OutputPtr output = config->output[o]; |
2689 | DisplayModePtr mode = modes[o]; |
2690 | xf86CrtcPtr crtc = crtcs[o]; |
2691 | |
2692 | if (mode && crtc) { |
2693 | xf86SaveModeContents(&crtc->desiredMode, mode); |
2694 | crtc->desiredRotation = output->initial_rotation; |
2695 | crtc->desiredX = output->initial_x; |
2696 | crtc->desiredY = output->initial_y; |
2697 | crtc->desiredTransformPresent = FALSE0; |
2698 | crtc->enabled = TRUE1; |
2699 | memcpy(&crtc->panningTotalArea, &output->initialTotalArea,__builtin___memcpy_chk (&crtc->panningTotalArea, & output->initialTotalArea, sizeof(BoxRec), __builtin_object_size (&crtc->panningTotalArea, 0)) |
2700 | sizeof(BoxRec))__builtin___memcpy_chk (&crtc->panningTotalArea, & output->initialTotalArea, sizeof(BoxRec), __builtin_object_size (&crtc->panningTotalArea, 0)); |
2701 | memcpy(&crtc->panningTrackingArea, &output->initialTrackingArea,__builtin___memcpy_chk (&crtc->panningTrackingArea, & output->initialTrackingArea, sizeof(BoxRec), __builtin_object_size (&crtc->panningTrackingArea, 0)) |
2702 | sizeof(BoxRec))__builtin___memcpy_chk (&crtc->panningTrackingArea, & output->initialTrackingArea, sizeof(BoxRec), __builtin_object_size (&crtc->panningTrackingArea, 0)); |
2703 | memcpy(crtc->panningBorder, output->initialBorder,__builtin___memcpy_chk (crtc->panningBorder, output->initialBorder , 4 * sizeof(INT16), __builtin_object_size (crtc->panningBorder , 0)) |
2704 | 4 * sizeof(INT16))__builtin___memcpy_chk (crtc->panningBorder, output->initialBorder , 4 * sizeof(INT16), __builtin_object_size (crtc->panningBorder , 0)); |
2705 | output->crtc = crtc; |
2706 | if (!xf86OutputSetInitialGamma(output)) |
2707 | xf86DrvMsg(scrn->scrnIndex, X_WARNING, |
2708 | "Initial gamma correction for output %s: failed.\n", |
2709 | output->name); |
2710 | } |
2711 | else { |
2712 | output->crtc = NULL((void*)0); |
2713 | } |
2714 | } |
2715 | |
2716 | if (scrn->display->virtualX == 0 || scrn->is_gpu) { |
2717 | /* |
2718 | * Expand virtual size to cover the current config and potential mode |
2719 | * switches, if the driver can't enlarge the screen later. |
2720 | */ |
2721 | xf86DefaultScreenLimits(scrn, &width, &height, canGrow); |
2722 | |
2723 | if (have_outputs == FALSE0) { |
2724 | if (width < NO_OUTPUT_DEFAULT_WIDTH1024 && |
2725 | height < NO_OUTPUT_DEFAULT_HEIGHT768) { |
2726 | width = NO_OUTPUT_DEFAULT_WIDTH1024; |
2727 | height = NO_OUTPUT_DEFAULT_HEIGHT768; |
2728 | } |
2729 | } |
2730 | |
2731 | if (!scrn->is_gpu) { |
2732 | scrn->display->virtualX = width; |
2733 | scrn->display->virtualY = height; |
2734 | } |
2735 | } |
2736 | |
2737 | if (width > scrn->virtualX) |
2738 | scrn->virtualX = width; |
2739 | if (height > scrn->virtualY) |
2740 | scrn->virtualY = height; |
2741 | |
2742 | /* |
2743 | * Make sure the configuration isn't too small. |
2744 | */ |
2745 | if (width < config->minWidth || height < config->minHeight) |
2746 | goto bailout; |
2747 | |
2748 | /* |
2749 | * Limit the crtc config to virtual[XY] if the driver can't grow the |
2750 | * desktop. |
2751 | */ |
2752 | if (!canGrow) { |
2753 | xf86CrtcSetSizeRange(scrn, config->minWidth, config->minHeight, |
2754 | width, height); |
2755 | } |
2756 | |
2757 | xf86SetScrnInfoModes(scrn); |
2758 | |
2759 | success = TRUE1; |
2760 | bailout: |
2761 | free(crtcs); |
2762 | free(modes); |
2763 | free(enabled); |
2764 | return success; |
2765 | } |
2766 | |
2767 | /* |
2768 | * Check the CRTC we're going to map each output to vs. it's current |
2769 | * CRTC. If they don't match, we have to disable the output and the CRTC |
2770 | * since the driver will have to re-route things. |
2771 | */ |
2772 | static void |
2773 | xf86PrepareOutputs(ScrnInfoPtr scrn) |
2774 | { |
2775 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
2776 | int o; |
2777 | |
2778 | for (o = 0; o < config->num_output; o++) { |
2779 | xf86OutputPtr output = config->output[o]; |
2780 | |
2781 | #if RANDR_GET_CRTC_INTERFACE1 |
2782 | /* Disable outputs that are unused or will be re-routed */ |
2783 | if (!output->funcs->get_crtc || |
2784 | output->crtc != (*output->funcs->get_crtc) (output) || |
2785 | output->crtc == NULL((void*)0)) |
2786 | #endif |
2787 | (*output->funcs->dpms) (output, DPMSModeOff3); |
2788 | } |
2789 | } |
2790 | |
2791 | static void |
2792 | xf86PrepareCrtcs(ScrnInfoPtr scrn) |
2793 | { |
2794 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
2795 | int c; |
2796 | |
2797 | for (c = 0; c < config->num_crtc; c++) { |
2798 | #if RANDR_GET_CRTC_INTERFACE1 |
2799 | xf86CrtcPtr crtc = config->crtc[c]; |
2800 | xf86OutputPtr output = NULL((void*)0); |
2801 | uint32_t desired_outputs = 0, current_outputs = 0; |
2802 | int o; |
2803 | |
2804 | for (o = 0; o < config->num_output; o++) { |
2805 | output = config->output[o]; |
2806 | if (output->crtc == crtc) |
2807 | desired_outputs |= (1 << o); |
2808 | /* If we can't tell where it's mapped, force it off */ |
2809 | if (!output->funcs->get_crtc) { |
2810 | desired_outputs = 0; |
2811 | break; |
2812 | } |
2813 | if ((*output->funcs->get_crtc) (output) == crtc) |
2814 | current_outputs |= (1 << o); |
2815 | } |
2816 | |
2817 | /* |
2818 | * If mappings are different or the CRTC is unused, |
2819 | * we need to disable it |
2820 | */ |
2821 | if (desired_outputs != current_outputs || !desired_outputs) |
2822 | (*crtc->funcs->dpms) (crtc, DPMSModeOff3); |
2823 | #else |
2824 | (*crtc->funcs->dpms) (crtc, DPMSModeOff3); |
2825 | #endif |
2826 | } |
2827 | } |
2828 | |
2829 | /* |
2830 | * Using the desired mode information in each crtc, set |
2831 | * modes (used in EnterVT functions, or at server startup) |
2832 | */ |
2833 | |
2834 | Bool |
2835 | xf86SetDesiredModes(ScrnInfoPtr scrn) |
2836 | { |
2837 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
2838 | xf86CrtcPtr crtc = config->crtc[0]; |
2839 | int enabled = 0, failed = 0; |
2840 | int c; |
2841 | |
2842 | /* A driver with this hook will take care of this */ |
2843 | if (!crtc->funcs->set_mode_major) { |
2844 | xf86PrepareOutputs(scrn); |
2845 | xf86PrepareCrtcs(scrn); |
2846 | } |
2847 | |
2848 | for (c = 0; c < config->num_crtc; c++) { |
2849 | xf86OutputPtr output = NULL((void*)0); |
2850 | int o; |
2851 | RRTransformPtr transform; |
2852 | |
2853 | crtc = config->crtc[c]; |
2854 | |
2855 | /* Skip disabled CRTCs */ |
2856 | if (!crtc->enabled) |
2857 | continue; |
2858 | |
2859 | if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc) |
2860 | output = xf86CompatOutput(scrn); |
2861 | else { |
2862 | for (o = 0; o < config->num_output; o++) |
2863 | if (config->output[o]->crtc == crtc) { |
2864 | output = config->output[o]; |
2865 | break; |
2866 | } |
2867 | } |
2868 | /* paranoia */ |
2869 | if (!output) |
2870 | continue; |
2871 | |
2872 | /* Mark that we'll need to re-set the mode for sure */ |
2873 | memset(&crtc->mode, 0, sizeof(crtc->mode))__builtin___memset_chk (&crtc->mode, 0, sizeof(crtc-> mode), __builtin_object_size (&crtc->mode, 0)); |
2874 | if (!crtc->desiredMode.CrtcHDisplay) { |
2875 | DisplayModePtr mode = |
2876 | xf86OutputFindClosestMode(output, scrn->currentMode); |
2877 | |
2878 | if (!mode) |
2879 | return FALSE0; |
2880 | xf86SaveModeContents(&crtc->desiredMode, mode); |
2881 | crtc->desiredRotation = RR_Rotate_01; |
2882 | crtc->desiredTransformPresent = FALSE0; |
2883 | crtc->desiredX = 0; |
2884 | crtc->desiredY = 0; |
2885 | } |
2886 | |
2887 | if (crtc->desiredTransformPresent) |
2888 | transform = &crtc->desiredTransform; |
2889 | else |
2890 | transform = NULL((void*)0); |
2891 | if (xf86CrtcSetModeTransform |
2892 | (crtc, &crtc->desiredMode, crtc->desiredRotation, transform, |
2893 | crtc->desiredX, crtc->desiredY)) { |
2894 | ++enabled; |
2895 | } else { |
2896 | for (o = 0; o < config->num_output; o++) |
2897 | if (config->output[o]->crtc == crtc) |
2898 | config->output[o]->crtc = NULL((void*)0); |
2899 | crtc->enabled = FALSE0; |
2900 | ++failed; |
2901 | } |
2902 | } |
2903 | |
2904 | xf86DisableUnusedFunctions(scrn); |
2905 | return enabled != 0 || failed == 0; |
2906 | } |
2907 | |
2908 | /** |
2909 | * In the current world order, there are lists of modes per output, which may |
2910 | * or may not include the mode that was asked to be set by XFree86's mode |
2911 | * selection. Find the closest one, in the following preference order: |
2912 | * |
2913 | * - Equality |
2914 | * - Closer in size to the requested mode, but no larger |
2915 | * - Closer in refresh rate to the requested mode. |
2916 | */ |
2917 | |
2918 | DisplayModePtr |
2919 | xf86OutputFindClosestMode(xf86OutputPtr output, DisplayModePtr desired) |
2920 | { |
2921 | DisplayModePtr best = NULL((void*)0), scan = NULL((void*)0); |
2922 | |
2923 | for (scan = output->probed_modes; scan != NULL((void*)0); scan = scan->next) { |
2924 | /* If there's an exact match, we're done. */ |
2925 | if (xf86ModesEqual(scan, desired)) { |
2926 | best = desired; |
2927 | break; |
2928 | } |
2929 | |
2930 | /* Reject if it's larger than the desired mode. */ |
2931 | if (scan->HDisplay > desired->HDisplay || |
2932 | scan->VDisplay > desired->VDisplay) { |
2933 | continue; |
2934 | } |
2935 | |
2936 | /* |
2937 | * If we haven't picked a best mode yet, use the first |
2938 | * one in the size range |
2939 | */ |
2940 | if (best == NULL((void*)0)) { |
2941 | best = scan; |
2942 | continue; |
2943 | } |
2944 | |
2945 | /* Find if it's closer to the right size than the current best |
2946 | * option. |
2947 | */ |
2948 | if ((scan->HDisplay > best->HDisplay && |
2949 | scan->VDisplay >= best->VDisplay) || |
2950 | (scan->HDisplay >= best->HDisplay && |
2951 | scan->VDisplay > best->VDisplay)) { |
2952 | best = scan; |
2953 | continue; |
2954 | } |
2955 | |
2956 | /* Find if it's still closer to the right refresh than the current |
2957 | * best resolution. |
2958 | */ |
2959 | if (scan->HDisplay == best->HDisplay && |
2960 | scan->VDisplay == best->VDisplay && |
2961 | (fabs(scan->VRefresh - desired->VRefresh) < |
2962 | fabs(best->VRefresh - desired->VRefresh))) { |
2963 | best = scan; |
2964 | } |
2965 | } |
2966 | return best; |
2967 | } |
2968 | |
2969 | /** |
2970 | * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, |
2971 | * take the specified mode and apply it to the crtc connected to the compat |
2972 | * output. Then, find similar modes for the other outputs, as with the |
2973 | * InitialConfiguration code above. The goal is to clone the desired |
2974 | * mode across all outputs that are currently active. |
2975 | */ |
2976 | |
2977 | Bool |
2978 | xf86SetSingleMode(ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) |
2979 | { |
2980 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
2981 | Bool ok = TRUE1; |
2982 | xf86OutputPtr compat_output; |
2983 | DisplayModePtr compat_mode = NULL((void*)0); |
2984 | int c; |
2985 | |
2986 | /* |
2987 | * Let the compat output drive the final mode selection |
2988 | */ |
2989 | compat_output = xf86CompatOutput(pScrn); |
2990 | if (compat_output) |
2991 | compat_mode = xf86OutputFindClosestMode(compat_output, desired); |
2992 | if (compat_mode) |
2993 | desired = compat_mode; |
2994 | |
2995 | for (c = 0; c < config->num_crtc; c++) { |
2996 | xf86CrtcPtr crtc = config->crtc[c]; |
2997 | DisplayModePtr crtc_mode = NULL((void*)0); |
2998 | int o; |
2999 | |
3000 | if (!crtc->enabled) |
3001 | continue; |
3002 | |
3003 | for (o = 0; o < config->num_output; o++) { |
3004 | xf86OutputPtr output = config->output[o]; |
3005 | DisplayModePtr output_mode; |
3006 | |
3007 | /* skip outputs not on this crtc */ |
3008 | if (output->crtc != crtc) |
3009 | continue; |
3010 | |
3011 | if (crtc_mode) { |
3012 | output_mode = xf86OutputFindClosestMode(output, crtc_mode); |
3013 | if (output_mode != crtc_mode) |
3014 | output->crtc = NULL((void*)0); |
3015 | } |
3016 | else |
3017 | crtc_mode = xf86OutputFindClosestMode(output, desired); |
3018 | } |
3019 | if (!crtc_mode) { |
3020 | crtc->enabled = FALSE0; |
3021 | continue; |
3022 | } |
3023 | if (!xf86CrtcSetModeTransform(crtc, crtc_mode, rotation, NULL((void*)0), 0, 0)) |
3024 | ok = FALSE0; |
3025 | else { |
3026 | xf86SaveModeContents(&crtc->desiredMode, crtc_mode); |
3027 | crtc->desiredRotation = rotation; |
3028 | crtc->desiredTransformPresent = FALSE0; |
3029 | crtc->desiredX = 0; |
3030 | crtc->desiredY = 0; |
3031 | } |
3032 | } |
3033 | xf86DisableUnusedFunctions(pScrn); |
3034 | #ifdef RANDR_12_INTERFACE1 |
3035 | xf86RandR12TellChanged(pScrn->pScreen); |
3036 | #endif |
3037 | return ok; |
3038 | } |
3039 | |
3040 | /** |
3041 | * Set the DPMS power mode of all outputs and CRTCs. |
3042 | * |
3043 | * If the new mode is off, it will turn off outputs and then CRTCs. |
3044 | * Otherwise, it will affect CRTCs before outputs. |
3045 | */ |
3046 | void |
3047 | xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) |
3048 | { |
3049 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3050 | int i; |
3051 | |
3052 | if (!scrn->vtSema) |
3053 | return; |
3054 | |
3055 | if (mode == DPMSModeOff3) { |
3056 | for (i = 0; i < config->num_output; i++) { |
3057 | xf86OutputPtr output = config->output[i]; |
3058 | |
3059 | if (output->crtc != NULL((void*)0)) |
3060 | (*output->funcs->dpms) (output, mode); |
3061 | } |
3062 | } |
3063 | |
3064 | for (i = 0; i < config->num_crtc; i++) { |
3065 | xf86CrtcPtr crtc = config->crtc[i]; |
3066 | |
3067 | if (crtc->enabled) |
3068 | (*crtc->funcs->dpms) (crtc, mode); |
3069 | } |
3070 | |
3071 | if (mode != DPMSModeOff3) { |
3072 | for (i = 0; i < config->num_output; i++) { |
3073 | xf86OutputPtr output = config->output[i]; |
3074 | |
3075 | if (output->crtc != NULL((void*)0)) |
3076 | (*output->funcs->dpms) (output, mode); |
3077 | } |
3078 | } |
3079 | } |
3080 | |
3081 | /** |
3082 | * Implement the screensaver by just calling down into the driver DPMS hooks. |
3083 | * |
3084 | * Even for monitors with no DPMS support, by the definition of our DPMS hooks, |
3085 | * the outputs will still get disabled (blanked). |
3086 | */ |
3087 | Bool |
3088 | xf86SaveScreen(ScreenPtr pScreen, int mode) |
3089 | { |
3090 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); |
3091 | |
3092 | if (xf86IsUnblank(mode)) |
3093 | xf86DPMSSet(pScrn, DPMSModeOn0, 0); |
3094 | else |
3095 | xf86DPMSSet(pScrn, DPMSModeOff3, 0); |
3096 | |
3097 | return TRUE1; |
3098 | } |
3099 | |
3100 | /** |
3101 | * Disable all inactive crtcs and outputs |
3102 | */ |
3103 | void |
3104 | xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) |
3105 | { |
3106 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3107 | int o, c; |
3108 | |
3109 | for (o = 0; o < xf86_config->num_output; o++) { |
3110 | xf86OutputPtr output = xf86_config->output[o]; |
3111 | |
3112 | if (!output->crtc) |
3113 | (*output->funcs->dpms) (output, DPMSModeOff3); |
3114 | } |
3115 | |
3116 | for (c = 0; c < xf86_config->num_crtc; c++) { |
3117 | xf86CrtcPtr crtc = xf86_config->crtc[c]; |
3118 | |
3119 | if (!crtc->enabled) { |
3120 | crtc->funcs->dpms(crtc, DPMSModeOff3); |
3121 | memset(&crtc->mode, 0, sizeof(crtc->mode))__builtin___memset_chk (&crtc->mode, 0, sizeof(crtc-> mode), __builtin_object_size (&crtc->mode, 0)); |
3122 | xf86RotateDestroy(crtc); |
3123 | crtc->active = FALSE0; |
3124 | } |
3125 | } |
3126 | if (pScrn->pScreen) |
3127 | xf86_crtc_notify(pScrn->pScreen); |
3128 | if (pScrn->ModeSet) |
3129 | pScrn->ModeSet(pScrn); |
3130 | if (pScrn->pScreen) { |
3131 | if (pScrn->pScreen->isGPU) |
3132 | xf86CursorResetCursor(pScrn->pScreen->current_master); |
3133 | else |
3134 | xf86CursorResetCursor(pScrn->pScreen); |
3135 | } |
3136 | } |
3137 | |
3138 | #ifdef RANDR_12_INTERFACE1 |
3139 | |
3140 | #define EDID_ATOM_NAME"EDID" "EDID" |
3141 | |
3142 | /** |
3143 | * Set the RandR EDID property |
3144 | */ |
3145 | static void |
3146 | xf86OutputSetEDIDProperty(xf86OutputPtr output, void *data, int data_len) |
3147 | { |
3148 | Atom edid_atom = MakeAtom(EDID_ATOM_NAME"EDID", sizeof(EDID_ATOM_NAME"EDID") - 1, TRUE1); |
3149 | |
3150 | /* This may get called before the RandR resources have been created */ |
3151 | if (output->randr_output == NULL((void*)0)) |
3152 | return; |
3153 | |
3154 | if (data_len != 0) { |
3155 | RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER((Atom) 19), 8, |
3156 | PropModeReplace0, data_len, data, FALSE0, TRUE1); |
3157 | } |
3158 | else { |
3159 | RRDeleteOutputProperty(output->randr_output, edid_atom); |
3160 | } |
3161 | } |
3162 | |
3163 | #define TILE_ATOM_NAME"TILE" "TILE" |
3164 | /* changing this in the future could be tricky as people may hardcode 8 */ |
3165 | #define TILE_PROP_NUM_ITEMS8 8 |
3166 | static void |
3167 | xf86OutputSetTileProperty(xf86OutputPtr output) |
3168 | { |
3169 | Atom tile_atom = MakeAtom(TILE_ATOM_NAME"TILE", sizeof(TILE_ATOM_NAME"TILE") - 1, TRUE1); |
3170 | |
3171 | /* This may get called before the RandR resources have been created */ |
3172 | if (output->randr_output == NULL((void*)0)) |
3173 | return; |
3174 | |
3175 | if (output->tile_info.group_id != 0) { |
3176 | RRChangeOutputProperty(output->randr_output, tile_atom, XA_INTEGER((Atom) 19), 32, |
3177 | PropModeReplace0, TILE_PROP_NUM_ITEMS8, (uint32_t *)&output->tile_info, FALSE0, TRUE1); |
3178 | } |
3179 | else { |
3180 | RRDeleteOutputProperty(output->randr_output, tile_atom); |
3181 | } |
3182 | } |
3183 | |
3184 | #endif |
3185 | |
3186 | /* Pull out a phyiscal size from a detailed timing if available. */ |
3187 | struct det_phySize_parameter { |
3188 | xf86OutputPtr output; |
3189 | ddc_quirk_t quirks; |
3190 | Bool ret; |
3191 | }; |
3192 | |
3193 | static void |
3194 | handle_detailed_physical_size(struct detailed_monitor_section |
3195 | *det_mon, void *data) |
3196 | { |
3197 | struct det_phySize_parameter *p; |
3198 | |
3199 | p = (struct det_phySize_parameter *) data; |
3200 | |
3201 | if (p->ret == TRUE1) |
3202 | return; |
3203 | |
3204 | xf86DetTimingApplyQuirks(det_mon, p->quirks, |
3205 | p->output->MonInfo->features.hsize, |
3206 | p->output->MonInfo->features.vsize); |
3207 | if (det_mon->type == DT0 && |
3208 | det_mon->section.d_timings.h_size != 0 && |
3209 | det_mon->section.d_timings.v_size != 0) { |
3210 | /* some sanity checking for aspect ratio: |
3211 | assume any h / v (or v / h) > 2.4 to be bogus. |
3212 | This would even include cinemascope */ |
3213 | if (((det_mon->section.d_timings.h_size * 5) < |
3214 | (det_mon->section.d_timings.v_size * 12)) && |
3215 | ((det_mon->section.d_timings.v_size * 5) < |
3216 | (det_mon->section.d_timings.h_size * 12))) { |
3217 | p->output->mm_width = det_mon->section.d_timings.h_size; |
3218 | p->output->mm_height = det_mon->section.d_timings.v_size; |
3219 | p->ret = TRUE1; |
3220 | } else |
3221 | xf86DrvMsg(p->output->scrn->scrnIndex, X_WARNING, |
3222 | "Output %s: Strange aspect ratio (%i/%i), " |
3223 | "consider adding a quirk\n", p->output->name, |
3224 | det_mon->section.d_timings.h_size, |
3225 | det_mon->section.d_timings.v_size); |
3226 | } |
3227 | } |
3228 | |
3229 | Bool |
3230 | xf86OutputParseKMSTile(const char *tile_data, int tile_length, |
3231 | struct xf86CrtcTileInfo *tile_info) |
3232 | { |
3233 | int ret; |
3234 | |
3235 | ret = sscanf(tile_data, "%d:%d:%d:%d:%d:%d:%d:%d", |
3236 | &tile_info->group_id, |
3237 | &tile_info->flags, |
3238 | &tile_info->num_h_tile, |
3239 | &tile_info->num_v_tile, |
3240 | &tile_info->tile_h_loc, |
3241 | &tile_info->tile_v_loc, |
3242 | &tile_info->tile_h_size, |
3243 | &tile_info->tile_v_size); |
3244 | if (ret != 8) |
3245 | return FALSE0; |
3246 | return TRUE1; |
3247 | } |
3248 | |
3249 | void |
3250 | xf86OutputSetTile(xf86OutputPtr output, struct xf86CrtcTileInfo *tile_info) |
3251 | { |
3252 | if (tile_info) |
3253 | output->tile_info = *tile_info; |
3254 | else |
3255 | memset(&output->tile_info, 0, sizeof(output->tile_info))__builtin___memset_chk (&output->tile_info, 0, sizeof( output->tile_info), __builtin_object_size (&output-> tile_info, 0)); |
3256 | #ifdef RANDR_12_INTERFACE1 |
3257 | xf86OutputSetTileProperty(output); |
3258 | #endif |
3259 | } |
3260 | |
3261 | /** |
3262 | * Set the EDID information for the specified output |
3263 | */ |
3264 | void |
3265 | xf86OutputSetEDID(xf86OutputPtr output, xf86MonPtr edid_mon) |
3266 | { |
3267 | ScrnInfoPtr scrn = output->scrn; |
3268 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3269 | Bool debug_modes = config->debug_modes || xf86Initialising; |
3270 | |
3271 | #ifdef RANDR_12_INTERFACE1 |
3272 | int size; |
3273 | #endif |
3274 | |
3275 | free(output->MonInfo); |
3276 | |
3277 | output->MonInfo = edid_mon; |
3278 | output->mm_width = 0; |
3279 | output->mm_height = 0; |
3280 | |
3281 | if (debug_modes) { |
3282 | xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", |
3283 | output->name); |
3284 | xf86PrintEDID(edid_mon); |
3285 | } |
3286 | |
3287 | /* Set the DDC properties for the 'compat' output */ |
3288 | if (output == xf86CompatOutput(scrn)) |
3289 | xf86SetDDCproperties(scrn, edid_mon); |
3290 | |
3291 | #ifdef RANDR_12_INTERFACE1 |
3292 | /* Set the RandR output properties */ |
3293 | size = 0; |
3294 | if (edid_mon) { |
3295 | if (edid_mon->ver.version == 1) { |
3296 | size = 128; |
3297 | if (edid_mon->flags & EDID_COMPLETE_RAWDATA0x01) |
3298 | size += edid_mon->no_sections * 128; |
3299 | } |
3300 | else if (edid_mon->ver.version == 2) |
3301 | size = 256; |
3302 | } |
3303 | xf86OutputSetEDIDProperty(output, edid_mon ? edid_mon->rawData : NULL((void*)0), |
3304 | size); |
3305 | #endif |
3306 | |
3307 | if (edid_mon) { |
3308 | |
3309 | struct det_phySize_parameter p; |
3310 | |
3311 | p.output = output; |
3312 | p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex, edid_mon, FALSE0); |
3313 | p.ret = FALSE0; |
3314 | xf86ForEachDetailedBlock(edid_mon, handle_detailed_physical_size, &p); |
3315 | |
3316 | /* if no mm size is available from a detailed timing, check the max size field */ |
3317 | if ((!output->mm_width || !output->mm_height) && |
3318 | (edid_mon->features.hsize && edid_mon->features.vsize)) { |
3319 | output->mm_width = edid_mon->features.hsize * 10; |
3320 | output->mm_height = edid_mon->features.vsize * 10; |
3321 | } |
3322 | } |
3323 | } |
3324 | |
3325 | /** |
3326 | * Return the list of modes supported by the EDID information |
3327 | * stored in 'output' |
3328 | */ |
3329 | DisplayModePtr |
3330 | xf86OutputGetEDIDModes(xf86OutputPtr output) |
3331 | { |
3332 | ScrnInfoPtr scrn = output->scrn; |
3333 | xf86MonPtr edid_mon = output->MonInfo; |
3334 | |
3335 | if (!edid_mon) |
3336 | return NULL((void*)0); |
3337 | return xf86DDCGetModes(scrn->scrnIndex, edid_mon); |
3338 | } |
3339 | |
3340 | /* maybe we should care about DDC1? meh. */ |
3341 | xf86MonPtr |
3342 | xf86OutputGetEDID(xf86OutputPtr output, I2CBusPtr pDDCBus) |
3343 | { |
3344 | ScrnInfoPtr scrn = output->scrn; |
3345 | xf86MonPtr mon; |
3346 | |
3347 | mon = xf86DoEEDID(scrn, pDDCBus, TRUE1); |
3348 | if (mon) |
3349 | xf86DDCApplyQuirks(scrn->scrnIndex, mon); |
3350 | |
3351 | return mon; |
3352 | } |
3353 | |
3354 | static const char *_xf86ConnectorNames[] = { |
3355 | "None", "VGA", "DVI-I", "DVI-D", |
3356 | "DVI-A", "Composite", "S-Video", |
3357 | "Component", "LFP", "Proprietary", |
3358 | "HDMI", "DisplayPort", |
3359 | }; |
3360 | |
3361 | const char * |
3362 | xf86ConnectorGetName(xf86ConnectorType connector) |
3363 | { |
3364 | return _xf86ConnectorNames[connector]; |
3365 | } |
3366 | |
3367 | static void |
3368 | x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) |
3369 | { |
3370 | dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; |
3371 | dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; |
3372 | dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; |
3373 | dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; |
3374 | |
3375 | if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) |
3376 | dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; |
3377 | } |
3378 | |
3379 | static void |
3380 | x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) |
3381 | { |
3382 | if (crtc->enabled) { |
3383 | crtc_box->x1 = crtc->x; |
3384 | crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); |
3385 | crtc_box->y1 = crtc->y; |
3386 | crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); |
3387 | } |
3388 | else |
3389 | crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; |
3390 | } |
3391 | |
3392 | static int |
3393 | xf86_crtc_box_area(BoxPtr box) |
3394 | { |
3395 | return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); |
3396 | } |
3397 | |
3398 | #ifdef XV1 |
3399 | /* |
3400 | * Return the crtc covering 'box'. If two crtcs cover a portion of |
3401 | * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc |
3402 | * with greater coverage |
3403 | */ |
3404 | |
3405 | static xf86CrtcPtr |
3406 | xf86_covering_crtc(ScrnInfoPtr pScrn, |
3407 | BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret) |
3408 | { |
3409 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3410 | xf86CrtcPtr crtc, best_crtc; |
3411 | int coverage, best_coverage; |
3412 | int c; |
3413 | BoxRec crtc_box, cover_box; |
3414 | |
3415 | best_crtc = NULL((void*)0); |
3416 | best_coverage = 0; |
3417 | crtc_box_ret->x1 = 0; |
3418 | crtc_box_ret->x2 = 0; |
3419 | crtc_box_ret->y1 = 0; |
3420 | crtc_box_ret->y2 = 0; |
3421 | for (c = 0; c < xf86_config->num_crtc; c++) { |
3422 | crtc = xf86_config->crtc[c]; |
3423 | x86_crtc_box(crtc, &crtc_box); |
3424 | x86_crtc_box_intersect(&cover_box, &crtc_box, box); |
3425 | coverage = xf86_crtc_box_area(&cover_box); |
3426 | if (coverage && crtc == desired) { |
3427 | *crtc_box_ret = crtc_box; |
3428 | return crtc; |
3429 | } |
3430 | else if (coverage > best_coverage) { |
3431 | *crtc_box_ret = crtc_box; |
3432 | best_crtc = crtc; |
3433 | best_coverage = coverage; |
3434 | } |
3435 | } |
3436 | return best_crtc; |
3437 | } |
3438 | |
3439 | /* |
3440 | * For overlay video, compute the relevant CRTC and |
3441 | * clip video to that. |
3442 | * |
3443 | * returning FALSE means there was a memory failure of some kind, |
3444 | * not that the video shouldn't be displayed |
3445 | */ |
3446 | |
3447 | Bool |
3448 | xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, |
3449 | xf86CrtcPtr * crtc_ret, |
3450 | xf86CrtcPtr desired_crtc, |
3451 | BoxPtr dst, |
3452 | INT32 *xa, |
3453 | INT32 *xb, |
3454 | INT32 *ya, |
3455 | INT32 *yb, RegionPtr reg, INT32 width, INT32 height) |
3456 | { |
3457 | Bool ret; |
3458 | RegionRec crtc_region_local; |
3459 | RegionPtr crtc_region = reg; |
3460 | |
3461 | if (crtc_ret) { |
3462 | BoxRec crtc_box; |
3463 | xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, |
3464 | desired_crtc, |
3465 | &crtc_box); |
3466 | |
3467 | if (crtc) { |
3468 | RegionInit(&crtc_region_local, &crtc_box, 1); |
3469 | crtc_region = &crtc_region_local; |
3470 | RegionIntersect(crtc_region, crtc_region, reg); |
3471 | } |
3472 | *crtc_ret = crtc; |
3473 | } |
3474 | |
3475 | ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, |
3476 | crtc_region, width, height); |
3477 | |
3478 | if (crtc_region != reg) |
3479 | RegionUninit(&crtc_region_local); |
3480 | |
3481 | return ret; |
3482 | } |
3483 | #endif |
3484 | |
3485 | xf86_crtc_notify_proc_ptr |
3486 | xf86_wrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr new) |
3487 | { |
3488 | if (xf86CrtcConfigPrivateIndex != -1) { |
3489 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); |
3490 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3491 | xf86_crtc_notify_proc_ptr old; |
3492 | |
3493 | old = config->xf86_crtc_notify; |
3494 | config->xf86_crtc_notify = new; |
3495 | return old; |
3496 | } |
3497 | return NULL((void*)0); |
3498 | } |
3499 | |
3500 | void |
3501 | xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) |
3502 | { |
3503 | if (xf86CrtcConfigPrivateIndex != -1) { |
3504 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); |
3505 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3506 | |
3507 | config->xf86_crtc_notify = old; |
3508 | } |
3509 | } |
3510 | |
3511 | void |
3512 | xf86_crtc_notify(ScreenPtr screen) |
3513 | { |
3514 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); |
3515 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3516 | |
3517 | if (config->xf86_crtc_notify) |
3518 | config->xf86_crtc_notify(screen); |
3519 | } |
3520 | |
3521 | Bool |
3522 | xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) |
3523 | { |
3524 | if (xf86CrtcConfigPrivateIndex != -1) { |
3525 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3526 | xf86CrtcPtr crtc; |
3527 | |
3528 | /* for multiple drivers loaded we need this */ |
3529 | if (!xf86_config) |
3530 | return FALSE0; |
3531 | if (xf86_config->num_crtc == 0) |
3532 | return FALSE0; |
3533 | crtc = xf86_config->crtc[0]; |
3534 | |
3535 | return crtc->funcs->gamma_set != NULL((void*)0); |
3536 | } |
3537 | |
3538 | return FALSE0; |
3539 | } |
3540 | |
3541 | void |
3542 | xf86ProviderSetup(ScrnInfoPtr scrn, |
3543 | const xf86ProviderFuncsRec *funcs, const char *name) |
3544 | { |
3545 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3546 | |
3547 | assert(!xf86_config->name)(__builtin_expect(!(!xf86_config->name), 0) ? __assert_rtn (__func__, "xf86Crtc.c", 3547, "!xf86_config->name") : (void )0); |
3548 | assert(name)(__builtin_expect(!(name), 0) ? __assert_rtn(__func__, "xf86Crtc.c" , 3548, "name") : (void)0); |
3549 | |
3550 | xf86_config->name = strdup(name); |
3551 | xf86_config->provider_funcs = funcs; |
3552 | #ifdef RANDR_12_INTERFACE1 |
3553 | xf86_config->randr_provider = NULL((void*)0); |
3554 | #endif |
3555 | } |
3556 | |
3557 | void |
3558 | xf86DetachAllCrtc(ScrnInfoPtr scrn) |
3559 | { |
3560 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex ].ptr)); |
3561 | int i; |
3562 | |
3563 | for (i = 0; i < xf86_config->num_crtc; i++) { |
3564 | xf86CrtcPtr crtc = xf86_config->crtc[i]; |
3565 | |
3566 | if (crtc->randr_crtc) |
3567 | RRCrtcDetachScanoutPixmap(crtc->randr_crtc); |
3568 | |
3569 | /* dpms off */ |
3570 | (*crtc->funcs->dpms) (crtc, DPMSModeOff3); |
3571 | /* force a reset the next time its used */ |
3572 | crtc->randr_crtc->mode = NULL((void*)0); |
3573 | crtc->mode.HDisplay = 0; |
3574 | crtc->x = crtc->y = 0; |
3575 | } |
3576 | } |