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