Bug Summary

File:hw/xfree86/modes/xf86Crtc.c
Location:line 2242, column 9
Description:Value stored to 'output' is never read

Annotated Source Code

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
57int xf86CrtcConfigPrivateIndex = -1;
58
59void
60xf86CrtcConfigInit(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
74void
75xf86CrtcSetSizeRange(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 */
89xf86CrtcPtr
90xf86CrtcCreate(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
144void
145xf86CrtcDestroy(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
168Bool
169xf86CrtcInUse(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
181void
182xf86CrtcSetScreenSubpixelOrder(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 */
244Bool
245xf86CrtcSetModeTransform(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 */
395Bool
396xf86CrtcSetMode(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 */
405void
406xf86CrtcSetOrigin(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
427extern XF86ConfigPtr xf86configptr;
428
429typedef 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
448static 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
468enum {
469 OPTION_MODEDEBUG,
470};
471
472static OptionInfoRec xf86DeviceOptions[] = {
473 {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE0},
474 {-1, NULL((void*)0), OPTV_NONE, {0}, FALSE0},
475};
476
477static void
478xf86OutputSetMonitor(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
519static Bool
520xf86OutputEnabled(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
551static Bool
552xf86OutputIgnored(xf86OutputPtr output)
553{
554 return xf86ReturnOptValBool(output->options, OPTION_IGNORE, FALSE0);
555}
556
557static const char *direction[4] = {
558 "normal",
559 "left",
560 "inverted",
561 "right"
562};
563
564static Rotation
565xf86OutputInitialRotation(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
583xf86OutputPtr
584xf86OutputCreate(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
649Bool
650xf86OutputRename(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
666void
667xf86OutputUseScreenMonitor(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
675void
676xf86OutputDestroy(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 */
701static Bool
702xf86CrtcCreateScreenResources(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 */
721static Bool
722xf86CrtcCloseScreen(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
758int
759#else
760Bool
761#endif
762xf86CrtcScreenInit(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
812static DisplayModePtr
813xf86DefaultMode(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
851static DisplayModePtr
852xf86ClosestMode(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
891static DisplayModePtr
892xf86OutputHasPreferredMode(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
907static DisplayModePtr
908xf86OutputHasUserPreferredMode(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
919static int
920xf86PickCrtcs(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
1011static void
1012xf86DefaultScreenLimits(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 */
1078static Bool
1079xf86UserConfiguredOutputs(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
1119static Bool
1120xf86InitialOutputPositions(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
1298static void
1299xf86InitialPanning(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 */
1352static int
1353xf86ModeCompare(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 */
1370static DisplayModePtr
1371xf86SortModes(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
1403static const char *
1404preferredMode(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 */
1429static const char *
1430gettoken(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 */
1472static int
1473processZoomModes(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
1504static void
1505GuessRangeFromModes(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
1548enum det_monrec_source {
1549 sync_config, sync_edid, sync_default
1550};
1551
1552struct 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
1560static void
1561handle_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
1589void
1590xf86ProbeOutputModes(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
1844static DisplayModePtr
1845biggestMode(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
1863static xf86OutputPtr
1864SetCompatOutput(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
1947void
1948xf86SetScrnInfoModes(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
2000static Bool
2001xf86CollectEnabledOutputs(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
2030static Bool
2031nextEnabledOutput(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
2045static Bool
2046aspectMatch(float a, float b)
2047{
2048 return fabs(1 - (a / b)) < 0.05;
2049}
2050
2051static DisplayModePtr
2052nextAspectMode(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
2071static DisplayModePtr
2072bestModeForAspect(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
2105static Bool
2106xf86TargetPreferred(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
2219static Bool
2220xf86TargetAspect(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
2274static Bool
2275xf86TargetFallback(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
2313static Bool
2314xf86TargetUserpref(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
2330static Bool
2331xf86CrtcSetInitialGamma(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
2398static Bool
2399xf86OutputSetInitialGamma(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
2446Bool
2447xf86InitialConfiguration(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 */
2644static void
2645xf86PrepareOutputs(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
2663static void
2664xf86PrepareCrtcs(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
2706Bool
2707xf86SetDesiredModes(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
2790DisplayModePtr
2791xf86OutputFindClosestMode(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
2849Bool
2850xf86SetSingleMode(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 */
2918void
2919xf86DPMSSet(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 */
2959Bool
2960xf86SaveScreen(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 */
2975void
2976xf86DisableUnusedFunctions(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 */
3011static void
3012xf86OutputSetEDIDProperty(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. */
3032struct det_phySize_parameter {
3033 xf86OutputPtr output;
3034 ddc_quirk_t quirks;
3035 Bool ret;
3036};
3037
3038static void
3039handle_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 */
3077void
3078xf86OutputSetEDID(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 */
3142DisplayModePtr
3143xf86OutputGetEDIDModes(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. */
3154xf86MonPtr
3155xf86OutputGetEDID(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
3167static 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
3174const char *
3175xf86ConnectorGetName(xf86ConnectorType connector)
3176{
3177 return _xf86ConnectorNames[connector];
3178}
3179
3180static void
3181x86_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
3192static void
3193x86_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
3205static int
3206xf86_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
3218static xf86CrtcPtr
3219xf86_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
3260Bool
3261xf86_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
3298xf86_crtc_notify_proc_ptr
3299xf86_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
3313void
3314xf86_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
3324void
3325xf86_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
3334Bool
3335xf86_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
3354void
3355xf86ProviderSetup(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
3370void
3371xf86DetachAllCrtc(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}