2 * Copyright © 2006 Keith Packard
3 * Copyright © 2008 Red Hat, Inc.
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.
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
24 #ifdef HAVE_XORG_CONFIG_H
25 #include <xorg-config.h>
39 #include "xf86Modes.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"
51 #define NO_OUTPUT_DEFAULT_WIDTH 1024
52 #define NO_OUTPUT_DEFAULT_HEIGHT 768
54 * Initialize xf86CrtcConfig structure
57 int xf86CrtcConfigPrivateIndex
= -1;
60 xf86CrtcConfigInit(ScrnInfoPtr scrn
, const xf86CrtcConfigFuncsRec
* funcs
)
62 xf86CrtcConfigPtr config
;
64 if (xf86CrtcConfigPrivateIndex
== -1)
65 xf86CrtcConfigPrivateIndex
= xf86AllocateScrnInfoPrivateIndex();
66 config
= xnfcalloc(1, sizeof(xf86CrtcConfigRec
));
68 config
->funcs
= funcs
;
69 config
->compat_output
= -1;
71 scrn
->privates
[xf86CrtcConfigPrivateIndex
].ptr
= config
;
75 xf86CrtcSetSizeRange(ScrnInfoPtr scrn
,
76 int minWidth
, int minHeight
, int maxWidth
, int maxHeight
)
78 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
80 config
->minWidth
= minWidth
;
81 config
->minHeight
= minHeight
;
82 config
->maxWidth
= maxWidth
;
83 config
->maxHeight
= maxHeight
;
90 xf86CrtcCreate(ScrnInfoPtr scrn
, const xf86CrtcFuncsRec
* funcs
)
92 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
93 xf86CrtcPtr crtc
, *crtcs
;
95 crtc
= calloc(sizeof(xf86CrtcRec
), 1);
98 crtc
->version
= XF86_CRTC_VERSION
;
101 #ifdef RANDR_12_INTERFACE
102 crtc
->randr_crtc
= NULL
;
104 crtc
->rotation
= RR_Rotate_0
;
105 crtc
->desiredRotation
= RR_Rotate_0
;
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
);
112 crtc
->filter_width
= 0;
113 crtc
->filter_height
= 0;
114 crtc
->transform_in_use
= FALSE
;
115 crtc
->transformPresent
= FALSE
;
116 crtc
->desiredTransformPresent
= FALSE
;
117 memset(&crtc
->bounds
, '\0', sizeof(crtc
->bounds
));
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
) {
126 crtc
->gamma_green
= crtc
->gamma_red
+ crtc
->gamma_size
;
127 crtc
->gamma_blue
= crtc
->gamma_green
+ crtc
->gamma_size
;
129 if (xf86_config
->crtc
)
130 crtcs
= realloc(xf86_config
->crtc
,
131 (xf86_config
->num_crtc
+ 1) * sizeof(xf86CrtcPtr
));
133 crtcs
= malloc((xf86_config
->num_crtc
+ 1) * sizeof(xf86CrtcPtr
));
135 free(crtc
->gamma_red
);
139 xf86_config
->crtc
= crtcs
;
140 xf86_config
->crtc
[xf86_config
->num_crtc
++] = crtc
;
145 xf86CrtcDestroy(xf86CrtcPtr crtc
)
147 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(crtc
->scrn
);
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
],
154 &xf86_config
->crtc
[c
+ 1],
155 ((xf86_config
->num_crtc
- (c
+ 1)) * sizeof(void *)));
156 xf86_config
->num_crtc
--;
160 free(crtc
->gamma_red
);
165 * Return whether any outputs are connected to the specified pipe
169 xf86CrtcInUse(xf86CrtcPtr crtc
)
171 ScrnInfoPtr pScrn
= crtc
->scrn
;
172 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
175 for (o
= 0; o
< xf86_config
->num_output
; o
++)
176 if (xf86_config
->output
[o
]->crtc
== crtc
)
182 xf86CrtcSetScreenSubpixelOrder(ScreenPtr pScreen
)
184 int subpixel_order
= SubPixelUnknown
;
185 Bool has_none
= FALSE
;
186 ScrnInfoPtr scrn
= xf86ScreenToScrn(pScreen
);
187 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
190 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
191 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
193 for (o
= 0; o
< xf86_config
->num_output
; o
++) {
194 xf86OutputPtr output
= xf86_config
->output
[o
];
196 if (output
->crtc
== crtc
) {
197 switch (output
->subpixel_order
) {
201 case SubPixelUnknown
:
204 subpixel_order
= output
->subpixel_order
;
208 if (subpixel_order
!= SubPixelUnknown
)
211 if (subpixel_order
!= SubPixelUnknown
) {
212 static const int circle
[4] = {
213 SubPixelHorizontalRGB
,
215 SubPixelHorizontalBGR
,
221 for (rotate
= 0; rotate
< 4; rotate
++)
222 if (crtc
->rotation
& (1 << rotate
))
224 for (c
= 0; c
< 4; c
++)
225 if (circle
[c
] == subpixel_order
)
227 c
= (c
+ rotate
) & 0x3;
228 if ((crtc
->rotation
& RR_Reflect_X
) && !(c
& 1))
230 if ((crtc
->rotation
& RR_Reflect_Y
) && (c
& 1))
232 subpixel_order
= circle
[c
];
236 if (subpixel_order
== SubPixelUnknown
&& has_none
)
237 subpixel_order
= SubPixelNone
;
238 PictureSetSubpixelOrder(pScreen
, subpixel_order
);
242 * Sets the given video mode on the given crtc
245 xf86CrtcSetModeTransform(xf86CrtcPtr crtc
, DisplayModePtr mode
,
246 Rotation rotation
, RRTransformPtr transform
, int x
,
249 ScrnInfoPtr scrn
= crtc
->scrn
;
250 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
253 Bool didLock
= FALSE
;
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
;
261 crtc
->enabled
= xf86CrtcInUse(crtc
);
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
);
270 adjusted_mode
= xf86DuplicateMode(mode
);
272 saved_mode
= crtc
->mode
;
275 saved_rotation
= crtc
->rotation
;
276 if (crtc
->transformPresent
) {
277 RRTransformInit(&saved_transform
);
278 RRTransformCopy(&saved_transform
, &crtc
->transform
);
280 saved_transform_present
= crtc
->transformPresent
;
282 /* Update crtc values up front so the driver can rely on them for mode
288 crtc
->rotation
= rotation
;
290 RRTransformCopy(&crtc
->transform
, transform
);
291 crtc
->transformPresent
= TRUE
;
294 crtc
->transformPresent
= FALSE
;
296 if (crtc
->funcs
->set_mode_major
) {
297 ret
= crtc
->funcs
->set_mode_major(crtc
, mode
, rotation
, x
, y
);
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.
306 for (i
= 0; i
< xf86_config
->num_output
; i
++) {
307 xf86OutputPtr output
= xf86_config
->output
[i
];
309 if (output
->crtc
!= crtc
)
312 if (!output
->funcs
->mode_fixup(output
, mode
, adjusted_mode
)) {
317 if (!crtc
->funcs
->mode_fixup(crtc
, mode
, adjusted_mode
)) {
321 if (!xf86CrtcRotate(crtc
))
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
];
328 if (output
->crtc
!= crtc
)
331 /* Disable the output as the first thing we do. */
332 output
->funcs
->prepare(output
);
335 crtc
->funcs
->prepare(crtc
);
337 /* Set up the DPLL and any output state that needs to adjust or depend
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
];
344 if (output
->crtc
== crtc
)
345 output
->funcs
->mode_set(output
, mode
, adjusted_mode
);
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
);
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
];
358 if (output
->crtc
== crtc
)
359 output
->funcs
->commit(output
);
368 xf86CrtcSetScreenSubpixelOrder(scrn
->pScreen
);
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
;
382 free(adjusted_mode
->name
);
386 crtc
->funcs
->unlock(crtc
);
392 * Sets the given video mode on the given crtc, but without providing
396 xf86CrtcSetMode(xf86CrtcPtr crtc
, DisplayModePtr mode
, Rotation rotation
,
399 return xf86CrtcSetModeTransform(crtc
, mode
, rotation
, NULL
, x
, y
);
403 * Pans the screen, does not change the mode
406 xf86CrtcSetOrigin(xf86CrtcPtr crtc
, int x
, int y
)
408 ScrnInfoPtr scrn
= crtc
->scrn
;
412 if (crtc
->funcs
->set_origin
) {
413 if (!xf86CrtcRotate(crtc
))
415 crtc
->funcs
->set_origin(crtc
, x
, y
);
420 xf86CrtcSetMode(crtc
, &crtc
->mode
, crtc
->rotation
, x
, y
);
427 extern XF86ConfigPtr xf86configptr
;
430 OPTION_PREFERRED_MODE
,
445 OPTION_DEFAULT_MODES
,
448 static OptionInfoRec xf86OutputOptions
[] = {
449 {OPTION_PREFERRED_MODE
, "PreferredMode", OPTV_STRING
, {0}, FALSE
},
450 {OPTION_ZOOM_MODES
, "ZoomModes", OPTV_STRING
, {0}, FALSE
},
451 {OPTION_POSITION
, "Position", OPTV_STRING
, {0}, FALSE
},
452 {OPTION_BELOW
, "Below", OPTV_STRING
, {0}, FALSE
},
453 {OPTION_RIGHT_OF
, "RightOf", OPTV_STRING
, {0}, FALSE
},
454 {OPTION_ABOVE
, "Above", OPTV_STRING
, {0}, FALSE
},
455 {OPTION_LEFT_OF
, "LeftOf", OPTV_STRING
, {0}, FALSE
},
456 {OPTION_ENABLE
, "Enable", OPTV_BOOLEAN
, {0}, FALSE
},
457 {OPTION_DISABLE
, "Disable", OPTV_BOOLEAN
, {0}, FALSE
},
458 {OPTION_MIN_CLOCK
, "MinClock", OPTV_FREQ
, {0}, FALSE
},
459 {OPTION_MAX_CLOCK
, "MaxClock", OPTV_FREQ
, {0}, FALSE
},
460 {OPTION_IGNORE
, "Ignore", OPTV_BOOLEAN
, {0}, FALSE
},
461 {OPTION_ROTATE
, "Rotate", OPTV_STRING
, {0}, FALSE
},
462 {OPTION_PANNING
, "Panning", OPTV_STRING
, {0}, FALSE
},
463 {OPTION_PRIMARY
, "Primary", OPTV_BOOLEAN
, {0}, FALSE
},
464 {OPTION_DEFAULT_MODES
, "DefaultModes", OPTV_BOOLEAN
, {0}, FALSE
},
465 {-1, NULL
, OPTV_NONE
, {0}, FALSE
},
472 static OptionInfoRec xf86DeviceOptions
[] = {
473 {OPTION_MODEDEBUG
, "ModeDebug", OPTV_BOOLEAN
, {0}, FALSE
},
474 {-1, NULL
, OPTV_NONE
, {0}, FALSE
},
478 xf86OutputSetMonitor(xf86OutputPtr output
)
486 free(output
->options
);
488 output
->options
= xnfalloc(sizeof(xf86OutputOptions
));
489 memcpy(output
->options
, xf86OutputOptions
, sizeof(xf86OutputOptions
));
491 XNFasprintf(&option_name
, "monitor-%s", output
->name
);
492 monitor
= xf86findOptionValue(output
->scrn
->options
, option_name
);
494 monitor
= output
->name
;
496 xf86MarkOptionUsedByName(output
->scrn
->options
, option_name
);
498 output
->conf_monitor
= xf86findMonitor(monitor
,
499 xf86configptr
->conf_monitor_lst
);
501 * Find the monitor section of the screen and use that
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
,
515 xf86DrvMsg(output
->scrn
->scrnIndex
, X_INFO
,
516 "Output %s has no monitor section\n", output
->name
);
520 xf86OutputEnabled(xf86OutputPtr output
, Bool strict
)
522 Bool enable
, disable
;
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
);
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
);
537 /* If not, try to only light up the ones we know are connected */
539 enable
= output
->status
== XF86OutputStatusConnected
;
541 /* But if that fails, try to light up even outputs we're unsure of */
543 enable
= output
->status
!= XF86OutputStatusDisconnected
;
546 xf86DrvMsg(output
->scrn
->scrnIndex
, X_INFO
,
547 "Output %s %sconnected\n", output
->name
, enable
? "" : "dis");
552 xf86OutputIgnored(xf86OutputPtr output
)
554 return xf86ReturnOptValBool(output
->options
, OPTION_IGNORE
, FALSE
);
557 static const char *direction
[4] = {
565 xf86OutputInitialRotation(xf86OutputPtr output
)
567 char *rotate_name
= xf86GetOptValString(output
->options
,
572 if (output
->initial_rotation
)
573 return output
->initial_rotation
;
577 for (i
= 0; i
< 4; i
++)
578 if (xf86nameCompare(direction
[i
], rotate_name
) == 0)
584 xf86OutputCreate(ScrnInfoPtr scrn
,
585 const xf86OutputFuncsRec
* funcs
, const char *name
)
587 xf86OutputPtr output
, *outputs
;
588 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
593 len
= strlen(name
) + 1;
597 output
= calloc(sizeof(xf86OutputRec
) + len
, 1);
601 output
->funcs
= funcs
;
603 output
->name
= (char *) (output
+ 1);
604 strcpy(output
->name
, name
);
606 output
->subpixel_order
= SubPixelUnknown
;
608 * Use the old per-screen monitor section for the first output
610 output
->use_screen_monitor
= (xf86_config
->num_output
== 0);
611 #ifdef RANDR_12_INTERFACE
612 output
->randr_output
= NULL
;
615 xf86OutputSetMonitor(output
);
616 if (xf86OutputIgnored(output
)) {
622 if (xf86_config
->output
)
623 outputs
= realloc(xf86_config
->output
,
624 (xf86_config
->num_output
+
625 1) * sizeof(xf86OutputPtr
));
627 outputs
= malloc((xf86_config
->num_output
+ 1) * sizeof(xf86OutputPtr
));
633 xf86_config
->output
= outputs
;
635 if (xf86GetOptValBool(output
->options
, OPTION_PRIMARY
, &primary
) && primary
) {
636 memmove(xf86_config
->output
+ 1, xf86_config
->output
,
637 xf86_config
->num_output
* sizeof(xf86OutputPtr
));
638 xf86_config
->output
[0] = output
;
641 xf86_config
->output
[xf86_config
->num_output
] = output
;
644 xf86_config
->num_output
++;
650 xf86OutputRename(xf86OutputPtr output
, const char *name
)
652 char *newname
= strdup(name
);
655 return FALSE
; /* so sorry... */
657 if (output
->name
&& output
->name
!= (char *) (output
+ 1))
659 output
->name
= newname
;
660 xf86OutputSetMonitor(output
);
661 if (xf86OutputIgnored(output
))
667 xf86OutputUseScreenMonitor(xf86OutputPtr output
, Bool use_screen_monitor
)
669 if (use_screen_monitor
!= output
->use_screen_monitor
) {
670 output
->use_screen_monitor
= use_screen_monitor
;
671 xf86OutputSetMonitor(output
);
676 xf86OutputDestroy(xf86OutputPtr output
)
678 ScrnInfoPtr scrn
= output
->scrn
;
679 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
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
],
688 &xf86_config
->output
[o
+ 1],
689 ((xf86_config
->num_output
- (o
+ 1)) * sizeof(void *)));
690 xf86_config
->num_output
--;
693 if (output
->name
&& output
->name
!= (char *) (output
+ 1))
699 * Called during CreateScreenResources to hook up RandR
702 xf86CrtcCreateScreenResources(ScreenPtr screen
)
704 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
705 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
707 screen
->CreateScreenResources
= config
->CreateScreenResources
;
709 if (!(*screen
->CreateScreenResources
) (screen
))
712 if (!xf86RandR12CreateScreenResources(screen
))
719 * Clean up config on server reset
722 xf86CrtcCloseScreen(ScreenPtr screen
)
724 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
725 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
728 screen
->CloseScreen
= config
->CloseScreen
;
730 xf86RotateCloseScreen(screen
);
732 xf86RandR12CloseScreen(screen
);
734 screen
->CloseScreen(screen
);
736 for (o
= 0; o
< config
->num_output
; o
++) {
737 xf86OutputPtr output
= config
->output
[o
];
739 output
->randr_output
= NULL
;
741 for (c
= 0; c
< config
->num_crtc
; c
++) {
742 xf86CrtcPtr crtc
= config
->crtc
[c
];
744 crtc
->randr_crtc
= NULL
;
746 /* detach any providers */
747 if (config
->randr_provider
) {
748 RRProviderDestroy(config
->randr_provider
);
749 config
->randr_provider
= NULL
;
755 * Called at ScreenInit time to set up
757 #ifdef RANDR_13_INTERFACE
762 xf86CrtcScreenInit(ScreenPtr screen
)
764 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
765 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
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
);
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
];
778 if (!crtc
->funcs
->shadow_allocate
|| !crtc
->funcs
->shadow_create
)
781 if (c
== config
->num_crtc
) {
782 xf86RandR12SetRotations(screen
, RR_Rotate_0
| RR_Rotate_90
|
783 RR_Rotate_180
| RR_Rotate_270
|
784 RR_Reflect_X
| RR_Reflect_Y
);
785 xf86RandR12SetTransformSupport(screen
, TRUE
);
788 xf86RandR12SetRotations(screen
, RR_Rotate_0
);
789 xf86RandR12SetTransformSupport(screen
, FALSE
);
792 /* Wrap CreateScreenResources so we can initialize the RandR code */
793 config
->CreateScreenResources
= screen
->CreateScreenResources
;
794 screen
->CreateScreenResources
= xf86CrtcCreateScreenResources
;
796 config
->CloseScreen
= screen
->CloseScreen
;
797 screen
->CloseScreen
= xf86CrtcCloseScreen
;
799 /* This might still be marked wrapped from a previous generation */
800 config
->BlockHandler
= NULL
;
803 _xf86_di_dga_init_internal(screen
);
805 #ifdef RANDR_13_INTERFACE
806 return RANDR_INTERFACE_VERSION
;
812 static DisplayModePtr
813 xf86DefaultMode(xf86OutputPtr output
, int width
, int height
)
815 DisplayModePtr target_mode
= NULL
;
818 int target_preferred
= 0;
821 mm_height
= output
->mm_height
;
823 mm_height
= (768 * 25.4) / DEFAULT_DPI
;
825 * Pick a mode closest to DEFAULT_DPI
827 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
) {
829 int preferred
= (((mode
->type
& M_T_PREFERRED
) != 0) +
830 ((mode
->type
& M_T_USERPREF
) != 0));
833 if (xf86ModeWidth(mode
, output
->initial_rotation
) > width
||
834 xf86ModeHeight(mode
, output
->initial_rotation
) > height
)
837 /* yes, use VDisplay here, not xf86ModeHeight */
838 dpi
= (mode
->VDisplay
* 254) / (mm_height
* 10);
839 diff
= dpi
- DEFAULT_DPI
;
840 diff
= diff
< 0 ? -diff
: diff
;
841 if (target_mode
== NULL
|| (preferred
> target_preferred
) ||
842 (preferred
== target_preferred
&& diff
< target_diff
)) {
845 target_preferred
= preferred
;
851 static DisplayModePtr
852 xf86ClosestMode(xf86OutputPtr output
,
853 DisplayModePtr match
, Rotation match_rotation
,
854 int width
, int height
)
856 DisplayModePtr target_mode
= NULL
;
861 * Pick a mode closest to the specified mode
863 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
) {
867 if (xf86ModeWidth(mode
, output
->initial_rotation
) > width
||
868 xf86ModeHeight(mode
, output
->initial_rotation
) > height
)
871 /* exact matches are preferred */
872 if (output
->initial_rotation
== match_rotation
&&
873 xf86ModesEqual(mode
, match
))
876 dx
= xf86ModeWidth(match
, match_rotation
) - xf86ModeWidth(mode
,
879 dy
= xf86ModeHeight(match
, match_rotation
) - xf86ModeHeight(mode
,
882 diff
= dx
* dx
+ dy
* dy
;
883 if (target_mode
== NULL
|| diff
< target_diff
) {
891 static DisplayModePtr
892 xf86OutputHasPreferredMode(xf86OutputPtr output
, int width
, int height
)
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
)
901 if (mode
->type
& M_T_PREFERRED
)
907 static DisplayModePtr
908 xf86OutputHasUserPreferredMode(xf86OutputPtr output
)
910 DisplayModePtr mode
, first
= output
->probed_modes
;
912 for (mode
= first
; mode
&& mode
->next
!= first
; mode
= mode
->next
)
913 if (mode
->type
& M_T_USERPREF
)
920 xf86PickCrtcs(ScrnInfoPtr scrn
,
921 xf86CrtcPtr
* best_crtcs
,
922 DisplayModePtr
* modes
, int n
, int width
, int height
)
924 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
926 xf86OutputPtr output
;
929 xf86CrtcPtr best_crtc
;
934 if (n
== config
->num_output
)
936 output
= config
->output
[n
];
939 * Compute score with this output disabled
941 best_crtcs
[n
] = NULL
;
943 best_score
= xf86PickCrtcs(scrn
, best_crtcs
, modes
, n
+ 1, width
, height
);
944 if (modes
[n
] == NULL
)
947 crtcs
= malloc(config
->num_output
* sizeof(xf86CrtcPtr
));
952 /* Score outputs that are known to be connected higher */
953 if (output
->status
== XF86OutputStatusConnected
)
955 /* Score outputs with preferred modes higher */
956 if (xf86OutputHasPreferredMode(output
, width
, height
))
959 * Select a crtc for this output and
960 * then attempt to configure the remaining
963 for (c
= 0; c
< config
->num_crtc
; c
++) {
964 if ((output
->possible_crtcs
& (1 << c
)) == 0)
967 crtc
= config
->crtc
[c
];
969 * Check to see if some other output is
972 for (o
= 0; o
< n
; o
++)
973 if (best_crtcs
[o
] == crtc
)
977 * If the two outputs desire the same mode,
978 * see if they can be cloned
980 if (xf86ModesEqual(modes
[o
], modes
[n
]) &&
981 config
->output
[o
]->initial_rotation
==
982 config
->output
[n
]->initial_rotation
&&
983 config
->output
[o
]->initial_x
== config
->output
[n
]->initial_x
&&
984 config
->output
[o
]->initial_y
== config
->output
[n
]->initial_y
) {
985 if ((output
->possible_clones
& (1 << o
)) == 0)
986 continue; /* nope, try next CRTC */
989 continue; /* different modes, can't clone */
992 memcpy(crtcs
, best_crtcs
, n
* sizeof(xf86CrtcPtr
));
994 my_score
+ xf86PickCrtcs(scrn
, crtcs
, modes
, n
+ 1, width
, height
);
995 if (score
> best_score
) {
998 memcpy(best_crtcs
, crtcs
, config
->num_output
* sizeof(xf86CrtcPtr
));
1006 * Compute the virtual size necessary to place all of the available
1007 * crtcs in the specified configuration.
1009 * canGrow indicates that the driver can make the screen larger than its initial
1010 * configuration. If FALSE, this function will enlarge the screen to include
1011 * the largest available mode.
1015 xf86DefaultScreenLimits(ScrnInfoPtr scrn
, int *widthp
, int *heightp
,
1018 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1019 int width
= 0, height
= 0;
1024 for (c
= 0; c
< config
->num_crtc
; c
++) {
1025 int crtc_width
= 0, crtc_height
= 0;
1026 xf86CrtcPtr crtc
= config
->crtc
[c
];
1028 if (crtc
->enabled
) {
1030 crtc
->desiredX
+ xf86ModeWidth(&crtc
->desiredMode
,
1031 crtc
->desiredRotation
);
1033 crtc
->desiredY
+ xf86ModeHeight(&crtc
->desiredMode
,
1034 crtc
->desiredRotation
);
1037 for (o
= 0; o
< config
->num_output
; o
++) {
1038 xf86OutputPtr output
= config
->output
[o
];
1040 for (s
= 0; s
< config
->num_crtc
; s
++)
1041 if (output
->possible_crtcs
& (1 << s
)) {
1042 DisplayModePtr mode
;
1044 for (mode
= output
->probed_modes
; mode
;
1045 mode
= mode
->next
) {
1046 if (mode
->HDisplay
> crtc_width
)
1047 crtc_width
= mode
->HDisplay
;
1048 if (mode
->VDisplay
> crtc_width
)
1049 crtc_width
= mode
->VDisplay
;
1050 if (mode
->VDisplay
> crtc_height
)
1051 crtc_height
= mode
->VDisplay
;
1052 if (mode
->HDisplay
> crtc_height
)
1053 crtc_height
= mode
->HDisplay
;
1058 if (crtc_width
> width
)
1060 if (crtc_height
> height
)
1061 height
= crtc_height
;
1063 if (config
->maxWidth
&& width
> config
->maxWidth
)
1064 width
= config
->maxWidth
;
1065 if (config
->maxHeight
&& height
> config
->maxHeight
)
1066 height
= config
->maxHeight
;
1067 if (config
->minWidth
&& width
< config
->minWidth
)
1068 width
= config
->minWidth
;
1069 if (config
->minHeight
&& height
< config
->minHeight
)
1070 height
= config
->minHeight
;
1075 #define POSITION_UNSET -100000
1078 * check if the user configured any outputs at all
1079 * with either a position or a relative setting or a mode.
1082 xf86UserConfiguredOutputs(ScrnInfoPtr scrn
, DisplayModePtr
* modes
)
1084 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1086 Bool user_conf
= FALSE
;
1088 for (o
= 0; o
< config
->num_output
; o
++) {
1089 xf86OutputPtr output
= config
->output
[o
];
1091 char *relative_name
;
1092 OutputOpts relation
;
1095 static const OutputOpts relations
[] = {
1096 OPTION_BELOW
, OPTION_RIGHT_OF
, OPTION_ABOVE
, OPTION_LEFT_OF
1099 position
= xf86GetOptValString(output
->options
, OPTION_POSITION
);
1104 relative_name
= NULL
;
1105 for (r
= 0; r
< 4; r
++) {
1106 relation
= relations
[r
];
1107 relative_name
= xf86GetOptValString(output
->options
, relation
);
1114 modes
[o
] = xf86OutputHasUserPreferredMode(output
);
1123 xf86InitialOutputPositions(ScrnInfoPtr scrn
, DisplayModePtr
* modes
)
1125 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1129 for (o
= 0; o
< config
->num_output
; o
++) {
1130 xf86OutputPtr output
= config
->output
[o
];
1132 output
->initial_x
= output
->initial_y
= POSITION_UNSET
;
1136 * Loop until all outputs are set
1139 Bool any_set
= FALSE
;
1140 Bool keep_going
= FALSE
;
1142 for (o
= 0; o
< config
->num_output
; o
++) {
1143 static const OutputOpts relations
[] = {
1144 OPTION_BELOW
, OPTION_RIGHT_OF
, OPTION_ABOVE
, OPTION_LEFT_OF
1146 xf86OutputPtr output
= config
->output
[o
];
1147 xf86OutputPtr relative
;
1148 char *relative_name
;
1150 OutputOpts relation
;
1153 if (output
->initial_x
!= POSITION_UNSET
)
1155 position
= xf86GetOptValString(output
->options
, OPTION_POSITION
);
1157 * Absolute position wins
1162 if (sscanf(position
, "%d %d", &x
, &y
) == 2) {
1163 output
->initial_x
= x
;
1164 output
->initial_y
= y
;
1167 xf86DrvMsg(scrn
->scrnIndex
, X_ERROR
,
1168 "Output %s position not of form \"x y\"\n",
1170 output
->initial_x
= output
->initial_y
= 0;
1176 * Next comes relative positions
1179 relative_name
= NULL
;
1180 for (r
= 0; r
< 4; r
++) {
1181 relation
= relations
[r
];
1182 relative_name
= xf86GetOptValString(output
->options
, relation
);
1186 if (relative_name
) {
1190 for (or = 0; or < config
->num_output
; or++) {
1191 xf86OutputPtr out_rel
= config
->output
[or];
1192 XF86ConfMonitorPtr rel_mon
= out_rel
->conf_monitor
;
1195 if (xf86nameCompare(rel_mon
->mon_identifier
,
1196 relative_name
) == 0) {
1197 relative
= config
->output
[or];
1201 if (strcmp(out_rel
->name
, relative_name
) == 0) {
1202 relative
= config
->output
[or];
1207 xf86DrvMsg(scrn
->scrnIndex
, X_ERROR
,
1208 "Cannot position output %s relative to unknown output %s\n",
1209 output
->name
, relative_name
);
1210 output
->initial_x
= 0;
1211 output
->initial_y
= 0;
1216 xf86DrvMsg(scrn
->scrnIndex
, X_ERROR
,
1217 "Cannot position output %s relative to output %s without modes\n",
1218 output
->name
, relative_name
);
1219 output
->initial_x
= 0;
1220 output
->initial_y
= 0;
1224 if (relative
->initial_x
== POSITION_UNSET
) {
1228 output
->initial_x
= relative
->initial_x
;
1229 output
->initial_y
= relative
->initial_y
;
1232 output
->initial_y
+=
1233 xf86ModeHeight(modes
[or], relative
->initial_rotation
);
1235 case OPTION_RIGHT_OF
:
1236 output
->initial_x
+=
1237 xf86ModeWidth(modes
[or], relative
->initial_rotation
);
1241 output
->initial_y
-=
1242 xf86ModeHeight(modes
[o
], output
->initial_rotation
);
1244 case OPTION_LEFT_OF
:
1246 output
->initial_x
-=
1247 xf86ModeWidth(modes
[o
], output
->initial_rotation
);
1256 /* Nothing set, just stick them at 0,0 */
1257 output
->initial_x
= 0;
1258 output
->initial_y
= 0;
1264 for (o
= 0; o
< config
->num_output
; o
++) {
1265 xf86OutputPtr output
= config
->output
[o
];
1267 if (output
->initial_x
== POSITION_UNSET
) {
1268 xf86DrvMsg(scrn
->scrnIndex
, X_ERROR
,
1269 "Output position loop. Moving %s to 0,0\n",
1271 output
->initial_x
= output
->initial_y
= 0;
1279 * normalize positions
1283 for (o
= 0; o
< config
->num_output
; o
++) {
1284 xf86OutputPtr output
= config
->output
[o
];
1286 if (output
->initial_x
< min_x
)
1287 min_x
= output
->initial_x
;
1288 if (output
->initial_y
< min_y
)
1289 min_y
= output
->initial_y
;
1292 for (o
= 0; o
< config
->num_output
; o
++) {
1293 xf86OutputPtr output
= config
->output
[o
];
1295 output
->initial_x
-= min_x
;
1296 output
->initial_y
-= min_y
;
1302 xf86InitialPanning(ScrnInfoPtr scrn
)
1304 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1307 for (o
= 0; o
< config
->num_output
; o
++) {
1308 xf86OutputPtr output
= config
->output
[o
];
1309 char *panning
= xf86GetOptValString(output
->options
, OPTION_PANNING
);
1310 int width
, height
, left
, top
;
1311 int track_width
, track_height
, track_left
, track_top
;
1314 memset(&output
->initialTotalArea
, 0, sizeof(BoxRec
));
1315 memset(&output
->initialTrackingArea
, 0, sizeof(BoxRec
));
1316 memset(output
->initialBorder
, 0, 4 * sizeof(INT16
));
1321 switch (sscanf(panning
, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d",
1322 &width
, &height
, &left
, &top
,
1323 &track_width
, &track_height
, &track_left
, &track_top
,
1324 &brdr
[0], &brdr
[1], &brdr
[2], &brdr
[3])) {
1326 output
->initialBorder
[0] = brdr
[0];
1327 output
->initialBorder
[1] = brdr
[1];
1328 output
->initialBorder
[2] = brdr
[2];
1329 output
->initialBorder
[3] = brdr
[3];
1332 output
->initialTrackingArea
.x1
= track_left
;
1333 output
->initialTrackingArea
.y1
= track_top
;
1334 output
->initialTrackingArea
.x2
= track_left
+ track_width
;
1335 output
->initialTrackingArea
.y2
= track_top
+ track_height
;
1338 output
->initialTotalArea
.x1
= left
;
1339 output
->initialTotalArea
.y1
= top
;
1342 output
->initialTotalArea
.x2
= output
->initialTotalArea
.x1
+ width
;
1343 output
->initialTotalArea
.y2
= output
->initialTotalArea
.y1
+ height
;
1346 xf86DrvMsg(scrn
->scrnIndex
, X_ERROR
,
1347 "Broken panning specification '%s' for output %s in config file\n",
1348 panning
, output
->name
);
1353 /** Return - 0 + if a should be earlier, same or later than b in list
1356 xf86ModeCompare(DisplayModePtr a
, DisplayModePtr b
)
1360 diff
= ((b
->type
& M_T_PREFERRED
) != 0) - ((a
->type
& M_T_PREFERRED
) != 0);
1363 diff
= b
->HDisplay
* b
->VDisplay
- a
->HDisplay
* a
->VDisplay
;
1366 diff
= b
->Clock
- a
->Clock
;
1371 * Insertion sort input in-place and return the resulting head
1373 static DisplayModePtr
1374 xf86SortModes(DisplayModePtr input
)
1376 DisplayModePtr output
= NULL
, i
, o
, n
, *op
, prev
;
1378 /* sort by preferred status and pixel area */
1381 input
= input
->next
;
1382 for (op
= &output
; (o
= *op
); op
= &o
->next
)
1383 if (xf86ModeCompare(o
, i
) > 0)
1388 /* prune identical modes */
1389 for (o
= output
; o
&& (n
= o
->next
); o
= n
) {
1390 if (!strcmp(o
->name
, n
->name
) && xf86ModesEqual(o
, n
)) {
1397 /* hook up backward links */
1399 for (o
= output
; o
; o
= o
->next
) {
1407 preferredMode(ScrnInfoPtr pScrn
, xf86OutputPtr output
)
1409 char *preferred_mode
= NULL
;
1411 /* Check for a configured preference for a particular mode */
1412 preferred_mode
= xf86GetOptValString(output
->options
,
1413 OPTION_PREFERRED_MODE
);
1415 return preferred_mode
;
1417 if (pScrn
->display
->modes
&& *pScrn
->display
->modes
)
1418 preferred_mode
= *pScrn
->display
->modes
;
1420 return preferred_mode
;
1423 /** identify a token
1425 * *src a string with zero or more tokens, e.g. "tok0 tok1",
1426 * **token stores a pointer to the first token character,
1427 * *len stores the token length.
1429 * a pointer into src[] at the token terminating character, or
1430 * NULL if no token is found.
1433 gettoken(const char *src
, const char **token
, int *len
)
1435 const char *delim
= " \t";
1441 skip
= strspn(src
, delim
);
1442 *token
= &src
[skip
];
1444 *len
= strcspn(*token
, delim
);
1445 /* Support for backslash escaped delimiters could be implemented
1449 /* (*token)[0] != '\0' <==> *len > 0 */
1451 return &(*token
)[*len
];
1456 /** Check for a user configured zoom mode list, Option "ZoomModes":
1459 * Identifier "a21inch"
1460 * Option "ZoomModes" "1600x1200 1280x1024 1280x1024 640x480"
1463 * Each user mode name is searched for independently so the list
1464 * specification order is free. An output mode is matched at most
1465 * once, a mode with an already set M_T_USERDEF type bit is skipped.
1466 * Thus a repeat mode name specification matches the next output mode
1467 * with the same name.
1469 * Ctrl+Alt+Keypad-{Plus,Minus} zooms {in,out} by selecting the
1470 * {next,previous} M_T_USERDEF mode in the screen modes list, itself
1471 * sorted toward lower dot area or lower dot clock frequency, see
1472 * modes/xf86Crtc.c: xf86SortModes() xf86SetScrnInfoModes(), and
1473 * common/xf86Cursor.c: xf86ZoomViewport().
1476 processZoomModes(xf86OutputPtr output
)
1478 const char *zoom_modes
;
1481 zoom_modes
= xf86GetOptValString(output
->options
, OPTION_ZOOM_MODES
);
1484 const char *token
, *next
;
1487 next
= gettoken(zoom_modes
, &token
, &len
);
1489 DisplayModePtr mode
;
1491 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
)
1492 if (!strncmp(token
, mode
->name
, len
) /* prefix match */
1493 && mode
->name
[len
] == '\0' /* equal length */
1494 && !(mode
->type
& M_T_USERDEF
)) { /* no rematch */
1495 mode
->type
|= M_T_USERDEF
;
1500 next
= gettoken(next
, &token
, &len
);
1508 GuessRangeFromModes(MonPtr mon
, DisplayModePtr mode
)
1514 mon
->hsync
[0].lo
= 1024.0;
1515 mon
->hsync
[0].hi
= 0.0;
1518 mon
->vrefresh
[0].lo
= 1024.0;
1519 mon
->vrefresh
[0].hi
= 0.0;
1523 mode
->HSync
= ((float) mode
->Clock
) / ((float) mode
->HTotal
);
1525 if (!mode
->VRefresh
)
1526 mode
->VRefresh
= (1000.0 * ((float) mode
->Clock
)) /
1527 ((float) (mode
->HTotal
* mode
->VTotal
));
1529 if (mode
->HSync
< mon
->hsync
[0].lo
)
1530 mon
->hsync
[0].lo
= mode
->HSync
;
1532 if (mode
->HSync
> mon
->hsync
[0].hi
)
1533 mon
->hsync
[0].hi
= mode
->HSync
;
1535 if (mode
->VRefresh
< mon
->vrefresh
[0].lo
)
1536 mon
->vrefresh
[0].lo
= mode
->VRefresh
;
1538 if (mode
->VRefresh
> mon
->vrefresh
[0].hi
)
1539 mon
->vrefresh
[0].hi
= mode
->VRefresh
;
1544 /* stretch out the bottom to fit 640x480@60 */
1545 if (mon
->hsync
[0].lo
> 31.0)
1546 mon
->hsync
[0].lo
= 31.0;
1547 if (mon
->vrefresh
[0].lo
> 58.0)
1548 mon
->vrefresh
[0].lo
= 58.0;
1551 enum det_monrec_source
{
1552 sync_config
, sync_edid
, sync_default
1555 struct det_monrec_parameter
{
1560 enum det_monrec_source
*sync_source
;
1564 handle_detailed_monrec(struct detailed_monitor_section
*det_mon
, void *data
)
1566 struct det_monrec_parameter
*p
;
1568 p
= (struct det_monrec_parameter
*) data
;
1570 if (det_mon
->type
== DS_RANGES
) {
1571 struct monitor_ranges
*ranges
= &det_mon
->section
.ranges
;
1573 if (p
->set_hsync
&& ranges
->max_h
) {
1574 p
->mon_rec
->hsync
[p
->mon_rec
->nHsync
].lo
= ranges
->min_h
;
1575 p
->mon_rec
->hsync
[p
->mon_rec
->nHsync
].hi
= ranges
->max_h
;
1576 p
->mon_rec
->nHsync
++;
1577 if (*p
->sync_source
== sync_default
)
1578 *p
->sync_source
= sync_edid
;
1580 if (p
->set_vrefresh
&& ranges
->max_v
) {
1581 p
->mon_rec
->vrefresh
[p
->mon_rec
->nVrefresh
].lo
= ranges
->min_v
;
1582 p
->mon_rec
->vrefresh
[p
->mon_rec
->nVrefresh
].hi
= ranges
->max_v
;
1583 p
->mon_rec
->nVrefresh
++;
1584 if (*p
->sync_source
== sync_default
)
1585 *p
->sync_source
= sync_edid
;
1587 if (ranges
->max_clock
* 1000 > *p
->max_clock
)
1588 *p
->max_clock
= ranges
->max_clock
* 1000;
1593 xf86ProbeOutputModes(ScrnInfoPtr scrn
, int maxX
, int maxY
)
1595 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1598 /* When canGrow was TRUE in the initial configuration we have to
1599 * compare against the maximum values so that we don't drop modes.
1600 * When canGrow was FALSE, the maximum values would have been clamped
1603 if (maxX
== 0 || maxY
== 0) {
1604 maxX
= config
->maxWidth
;
1605 maxY
= config
->maxHeight
;
1608 /* Probe the list of modes for each output. */
1609 for (o
= 0; o
< config
->num_output
; o
++) {
1610 xf86OutputPtr output
= config
->output
[o
];
1611 DisplayModePtr mode
;
1612 DisplayModePtr config_modes
= NULL
, output_modes
, default_modes
= NULL
;
1613 char *preferred_mode
;
1614 xf86MonPtr edid_monitor
;
1615 XF86ConfMonitorPtr conf_monitor
;
1620 Bool add_default_modes
;
1621 Bool debug_modes
= config
->debug_modes
|| xf86Initialising
;
1622 enum det_monrec_source sync_source
= sync_default
;
1624 while (output
->probed_modes
!= NULL
)
1625 xf86DeleteMode(&output
->probed_modes
, output
->probed_modes
);
1628 * Check connection status
1630 output
->status
= (*output
->funcs
->detect
) (output
);
1632 if (output
->status
== XF86OutputStatusDisconnected
&&
1633 !xf86ReturnOptValBool(output
->options
, OPTION_ENABLE
, FALSE
)) {
1634 xf86OutputSetEDID(output
, NULL
);
1638 memset(&mon_rec
, '\0', sizeof(mon_rec
));
1640 conf_monitor
= output
->conf_monitor
;
1645 for (i
= 0; i
< conf_monitor
->mon_n_hsync
; i
++) {
1646 mon_rec
.hsync
[mon_rec
.nHsync
].lo
=
1647 conf_monitor
->mon_hsync
[i
].lo
;
1648 mon_rec
.hsync
[mon_rec
.nHsync
].hi
=
1649 conf_monitor
->mon_hsync
[i
].hi
;
1651 sync_source
= sync_config
;
1653 for (i
= 0; i
< conf_monitor
->mon_n_vrefresh
; i
++) {
1654 mon_rec
.vrefresh
[mon_rec
.nVrefresh
].lo
=
1655 conf_monitor
->mon_vrefresh
[i
].lo
;
1656 mon_rec
.vrefresh
[mon_rec
.nVrefresh
].hi
=
1657 conf_monitor
->mon_vrefresh
[i
].hi
;
1658 mon_rec
.nVrefresh
++;
1659 sync_source
= sync_config
;
1661 config_modes
= xf86GetMonitorModes(scrn
, conf_monitor
);
1664 output_modes
= (*output
->funcs
->get_modes
) (output
);
1667 * If the user has a preference, respect it.
1668 * Otherwise, don't second-guess the driver.
1670 if (!xf86GetOptValBool(output
->options
, OPTION_DEFAULT_MODES
,
1671 &add_default_modes
))
1672 add_default_modes
= (output_modes
== NULL
);
1674 edid_monitor
= output
->MonInfo
;
1677 struct det_monrec_parameter p
;
1678 struct disp_features
*features
= &edid_monitor
->features
;
1680 /* if display is not continuous-frequency, don't add default modes */
1681 if (!GTF_SUPPORTED(features
->msc
))
1682 add_default_modes
= FALSE
;
1684 p
.mon_rec
= &mon_rec
;
1685 p
.max_clock
= &max_clock
;
1686 p
.set_hsync
= mon_rec
.nHsync
== 0;
1687 p
.set_vrefresh
= mon_rec
.nVrefresh
== 0;
1688 p
.sync_source
= &sync_source
;
1690 xf86ForEachDetailedBlock(edid_monitor
, handle_detailed_monrec
, &p
);
1693 if (xf86GetOptValFreq(output
->options
, OPTION_MIN_CLOCK
,
1694 OPTUNITS_KHZ
, &clock
))
1695 min_clock
= (int) clock
;
1696 if (xf86GetOptValFreq(output
->options
, OPTION_MAX_CLOCK
,
1697 OPTUNITS_KHZ
, &clock
))
1698 max_clock
= (int) clock
;
1700 /* If we still don't have a sync range, guess wildly */
1701 if (!mon_rec
.nHsync
|| !mon_rec
.nVrefresh
)
1702 GuessRangeFromModes(&mon_rec
, output_modes
);
1705 * These limits will end up setting a 1024x768@60Hz mode by default,
1706 * which seems like a fairly good mode to use when nothing else is
1709 if (mon_rec
.nHsync
== 0) {
1710 mon_rec
.hsync
[0].lo
= 31.0;
1711 mon_rec
.hsync
[0].hi
= 55.0;
1714 if (mon_rec
.nVrefresh
== 0) {
1715 mon_rec
.vrefresh
[0].lo
= 58.0;
1716 mon_rec
.vrefresh
[0].hi
= 62.0;
1717 mon_rec
.nVrefresh
= 1;
1720 if (add_default_modes
)
1721 default_modes
= xf86GetDefaultModes();
1724 * If this is not an RB monitor, remove RB modes from the default
1725 * pool. RB modes from the config or the monitor itself are fine.
1727 if (!mon_rec
.reducedblanking
)
1728 xf86ValidateModesReducedBlanking(scrn
, default_modes
);
1730 if (sync_source
== sync_config
) {
1732 * Check output and config modes against sync range from config file
1734 xf86ValidateModesSync(scrn
, output_modes
, &mon_rec
);
1735 xf86ValidateModesSync(scrn
, config_modes
, &mon_rec
);
1738 * Check default modes against sync range
1740 xf86ValidateModesSync(scrn
, default_modes
, &mon_rec
);
1742 * Check default modes against monitor max clock
1745 xf86ValidateModesClocks(scrn
, default_modes
,
1746 &min_clock
, &max_clock
, 1);
1747 xf86ValidateModesClocks(scrn
, output_modes
,
1748 &min_clock
, &max_clock
, 1);
1751 output
->probed_modes
= NULL
;
1752 output
->probed_modes
= xf86ModesAdd(output
->probed_modes
, config_modes
);
1753 output
->probed_modes
= xf86ModesAdd(output
->probed_modes
, output_modes
);
1754 output
->probed_modes
=
1755 xf86ModesAdd(output
->probed_modes
, default_modes
);
1758 * Check all modes against max size, interlace, and doublescan
1761 xf86ValidateModesSize(scrn
, output
->probed_modes
, maxX
, maxY
, 0);
1764 int flags
= (output
->interlaceAllowed
? V_INTERLACE
: 0) |
1765 (output
->doubleScanAllowed
? V_DBLSCAN
: 0);
1766 xf86ValidateModesFlags(scrn
, output
->probed_modes
, flags
);
1770 * Check all modes against output
1772 for (mode
= output
->probed_modes
; mode
!= NULL
; mode
= mode
->next
)
1773 if (mode
->status
== MODE_OK
)
1774 mode
->status
= (*output
->funcs
->mode_valid
) (output
, mode
);
1776 xf86PruneInvalidModes(scrn
, &output
->probed_modes
, debug_modes
);
1778 output
->probed_modes
= xf86SortModes(output
->probed_modes
);
1780 /* Check for a configured preference for a particular mode */
1781 preferred_mode
= preferredMode(scrn
, output
);
1783 if (preferred_mode
) {
1784 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
) {
1785 if (!strcmp(preferred_mode
, mode
->name
)) {
1786 if (mode
!= output
->probed_modes
) {
1788 mode
->prev
->next
= mode
->next
;
1790 mode
->next
->prev
= mode
->prev
;
1791 mode
->next
= output
->probed_modes
;
1792 output
->probed_modes
->prev
= mode
;
1794 output
->probed_modes
= mode
;
1796 mode
->type
|= (M_T_PREFERRED
| M_T_USERPREF
);
1802 /* Ctrl+Alt+Keypad-{Plus,Minus} zoom mode: M_T_USERDEF mode type */
1803 processZoomModes(output
);
1805 output
->initial_rotation
= xf86OutputInitialRotation(output
);
1808 if (output
->probed_modes
!= NULL
) {
1809 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
,
1810 "Printing probed modes for output %s\n",
1814 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
,
1815 "No remaining probed modes for output %s\n",
1819 for (mode
= output
->probed_modes
; mode
!= NULL
; mode
= mode
->next
) {
1820 /* The code to choose the best mode per pipe later on will require
1821 * VRefresh to be set.
1823 mode
->VRefresh
= xf86ModeVRefresh(mode
);
1824 xf86SetModeCrtc(mode
, INTERLACE_HALVE_V
);
1827 xf86PrintModeline(scrn
->scrnIndex
, mode
);
1833 * Copy one of the output mode lists to the ScrnInfo record
1836 /* XXX where does this function belong? Here? */
1838 xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn
, int *x
, int *y
);
1840 static DisplayModePtr
1841 biggestMode(DisplayModePtr a
, DisplayModePtr b
)
1850 A
= a
->HDisplay
* a
->VDisplay
;
1851 B
= b
->HDisplay
* b
->VDisplay
;
1859 static xf86OutputPtr
1860 SetCompatOutput(xf86CrtcConfigPtr config
)
1862 xf86OutputPtr output
= NULL
, test
= NULL
;
1863 DisplayModePtr maxmode
= NULL
, testmode
, mode
;
1864 int o
, compat
= -1, count
, mincount
= 0;
1866 if (config
->num_output
== 0)
1869 /* Look for one that's definitely connected */
1870 for (o
= 0; o
< config
->num_output
; o
++) {
1871 test
= config
->output
[o
];
1874 if (test
->status
!= XF86OutputStatusConnected
)
1876 if (!test
->probed_modes
)
1879 testmode
= mode
= test
->probed_modes
;
1880 for (count
= 0; mode
; mode
= mode
->next
, count
++)
1881 testmode
= biggestMode(testmode
, mode
);
1889 else if (maxmode
== biggestMode(maxmode
, testmode
)) {
1895 else if ((maxmode
->HDisplay
== testmode
->HDisplay
) &&
1896 (maxmode
->VDisplay
== testmode
->VDisplay
) &&
1897 count
<= mincount
) {
1905 /* If we didn't find one, take anything we can get */
1907 for (o
= 0; o
< config
->num_output
; o
++) {
1908 test
= config
->output
[o
];
1911 if (!test
->probed_modes
)
1918 else if (test
->probed_modes
->HDisplay
<
1919 output
->probed_modes
->HDisplay
) {
1927 config
->compat_output
= compat
;
1929 else if (config
->compat_output
>= 0 && config
->compat_output
< config
->num_output
) {
1930 /* Don't change the compat output when no valid outputs found */
1931 output
= config
->output
[config
->compat_output
];
1934 /* All outputs are disconnected, select one to fake */
1935 if (!output
&& config
->num_output
) {
1936 config
->compat_output
= 0;
1937 output
= config
->output
[config
->compat_output
];
1944 xf86SetScrnInfoModes(ScrnInfoPtr scrn
)
1946 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1947 xf86OutputPtr output
;
1949 DisplayModePtr last
, mode
= NULL
;
1951 output
= SetCompatOutput(config
);
1956 crtc
= output
->crtc
;
1958 /* Clear any existing modes from scrn->modes */
1959 while (scrn
->modes
!= NULL
)
1960 xf86DeleteMode(&scrn
->modes
, scrn
->modes
);
1962 /* Set scrn->modes to the mode list for the 'compat' output */
1963 scrn
->modes
= xf86DuplicateModes(scrn
, output
->probed_modes
);
1966 for (mode
= scrn
->modes
; mode
; mode
= mode
->next
)
1967 if (xf86ModesEqual(mode
, &crtc
->desiredMode
))
1972 scrn
->modes
= xf86ModesAdd(scrn
->modes
,
1973 xf86CVTMode(scrn
->display
->virtualX
,
1974 scrn
->display
->virtualY
,
1978 /* For some reason, scrn->modes is circular, unlike the other mode
1979 * lists. How great is that?
1981 for (last
= scrn
->modes
; last
&& last
->next
; last
= last
->next
);
1982 last
->next
= scrn
->modes
;
1983 scrn
->modes
->prev
= last
;
1985 while (scrn
->modes
!= mode
)
1986 scrn
->modes
= scrn
->modes
->next
;
1989 scrn
->currentMode
= scrn
->modes
;
1992 _xf86_di_dga_reinit_internal(scrn
->pScreen
);
1997 xf86CollectEnabledOutputs(ScrnInfoPtr scrn
, xf86CrtcConfigPtr config
,
2000 Bool any_enabled
= FALSE
;
2004 * Don't bother enabling outputs on GPU screens: a client needs to attach
2005 * it to a source provider before setting a mode that scans out a shared
2011 for (o
= 0; o
< config
->num_output
; o
++)
2012 any_enabled
|= enabled
[o
] = xf86OutputEnabled(config
->output
[o
], TRUE
);
2015 xf86DrvMsg(scrn
->scrnIndex
, X_WARNING
,
2016 "No outputs definitely connected, trying again...\n");
2018 for (o
= 0; o
< config
->num_output
; o
++)
2019 any_enabled
|= enabled
[o
] =
2020 xf86OutputEnabled(config
->output
[o
], FALSE
);
2027 nextEnabledOutput(xf86CrtcConfigPtr config
, Bool
*enabled
, int *index
)
2031 for (o
++; o
< config
->num_output
; o
++) {
2042 aspectMatch(float a
, float b
)
2044 return fabs(1 - (a
/ b
)) < 0.05;
2047 static DisplayModePtr
2048 nextAspectMode(xf86OutputPtr o
, DisplayModePtr last
, float aspect
)
2050 DisplayModePtr m
= NULL
;
2056 m
= o
->probed_modes
;
2060 for (; m
; m
= m
->next
)
2061 if (aspectMatch(aspect
, (float) m
->HDisplay
/ (float) m
->VDisplay
))
2067 static DisplayModePtr
2068 bestModeForAspect(xf86CrtcConfigPtr config
, Bool
*enabled
, float aspect
)
2071 DisplayModePtr mode
= NULL
, test
= NULL
, match
= NULL
;
2073 if (!nextEnabledOutput(config
, enabled
, &o
))
2075 while ((mode
= nextAspectMode(config
->output
[o
], mode
, aspect
))) {
2077 for (p
= o
; nextEnabledOutput(config
, enabled
, &p
);) {
2078 test
= xf86OutputFindClosestMode(config
->output
[p
], mode
);
2081 if (test
->HDisplay
!= mode
->HDisplay
||
2082 test
->VDisplay
!= mode
->VDisplay
) {
2088 /* if we didn't match it on all outputs, try the next one */
2092 /* if it's bigger than the last one, save it */
2093 if (!match
|| (test
->HDisplay
> match
->HDisplay
))
2097 /* return the biggest one found */
2102 xf86TargetPreferred(ScrnInfoPtr scrn
, xf86CrtcConfigPtr config
,
2103 DisplayModePtr
* modes
, Bool
*enabled
,
2104 int width
, int height
)
2107 int max_pref_width
= 0, max_pref_height
= 0;
2108 DisplayModePtr
*preferred
, *preferred_match
;
2111 preferred
= xnfcalloc(config
->num_output
, sizeof(DisplayModePtr
));
2112 preferred_match
= xnfcalloc(config
->num_output
, sizeof(DisplayModePtr
));
2114 /* Check if the preferred mode is available on all outputs */
2115 for (p
= -1; nextEnabledOutput(config
, enabled
, &p
);) {
2116 Rotation r
= config
->output
[p
]->initial_rotation
;
2117 DisplayModePtr mode
;
2119 if ((preferred
[p
] = xf86OutputHasPreferredMode(config
->output
[p
],
2121 int pref_width
= xf86ModeWidth(preferred
[p
], r
);
2122 int pref_height
= xf86ModeHeight(preferred
[p
], r
);
2123 Bool all_match
= TRUE
;
2125 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);) {
2127 xf86OutputPtr output
= config
->output
[o
];
2133 * First see if the preferred mode matches on the next
2134 * output as well. This catches the common case of identical
2135 * monitors and makes sure they all have the same timings
2136 * and refresh. If that fails, we fall back to trying to
2137 * match just width & height.
2139 mode
= xf86OutputHasPreferredMode(output
, pref_width
,
2141 if (mode
&& xf86ModesEqual(mode
, preferred
[p
])) {
2142 preferred
[o
] = mode
;
2146 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
) {
2147 Rotation r
= output
->initial_rotation
;
2149 if (xf86ModeWidth(mode
, r
) == pref_width
&&
2150 xf86ModeHeight(mode
, r
) == pref_height
) {
2151 preferred
[o
] = mode
;
2161 (pref_width
* pref_height
> max_pref_width
* max_pref_height
)) {
2162 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);)
2163 preferred_match
[o
] = preferred
[o
];
2164 max_pref_width
= pref_width
;
2165 max_pref_height
= pref_height
;
2172 * If there's no preferred mode, but only one monitor, pick the
2173 * biggest mode for its aspect ratio or 4:3, assuming one exists.
2179 DisplayModePtr a
= NULL
, b
= NULL
;
2181 /* count the number of enabled outputs */
2182 for (i
= 0, p
= -1; nextEnabledOutput(config
, enabled
, &p
); i
++);
2188 nextEnabledOutput(config
, enabled
, &p
);
2189 if (config
->output
[p
]->mm_height
)
2190 aspect
= (float) config
->output
[p
]->mm_width
/
2191 (float) config
->output
[p
]->mm_height
;
2193 a
= bestModeForAspect(config
, enabled
, 4.0/3.0);
2195 b
= bestModeForAspect(config
, enabled
, aspect
);
2197 preferred_match
[p
] = biggestMode(a
, b
);
2199 if (preferred_match
[p
])
2205 /* oh good, there is a match. stash the selected modes and return. */
2206 memcpy(modes
, preferred_match
,
2207 config
->num_output
* sizeof(DisplayModePtr
));
2211 free(preferred_match
);
2216 xf86TargetAspect(ScrnInfoPtr scrn
, xf86CrtcConfigPtr config
,
2217 DisplayModePtr
* modes
, Bool
*enabled
, int width
, int height
)
2220 float aspect
= 0.0, *aspects
;
2221 xf86OutputPtr output
;
2223 DisplayModePtr guess
= NULL
, aspect_guess
= NULL
, base_guess
= NULL
;
2225 aspects
= xnfcalloc(config
->num_output
, sizeof(float));
2227 /* collect the aspect ratios */
2228 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);) {
2229 output
= config
->output
[o
];
2230 if (output
->mm_height
)
2231 aspects
[o
] = (float) output
->mm_width
/ (float) output
->mm_height
;
2233 aspects
[o
] = 4.0 / 3.0;
2236 /* check that they're all the same */
2237 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);) {
2238 output
= config
->output
[o
];
2240 aspect
= aspects
[o
];
2242 else if (!aspectMatch(aspect
, aspects
[o
])) {
2243 goto no_aspect_match
;
2247 /* if they're all 4:3, just skip ahead and save effort */
2248 if (!aspectMatch(aspect
, 4.0 / 3.0))
2249 aspect_guess
= bestModeForAspect(config
, enabled
, aspect
);
2252 base_guess
= bestModeForAspect(config
, enabled
, 4.0 / 3.0);
2254 guess
= biggestMode(base_guess
, aspect_guess
);
2259 /* found a mode that works everywhere, now apply it */
2260 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);) {
2261 modes
[o
] = xf86OutputFindClosestMode(config
->output
[o
], guess
);
2271 xf86TargetFallback(ScrnInfoPtr scrn
, xf86CrtcConfigPtr config
,
2272 DisplayModePtr
* modes
, Bool
*enabled
, int width
, int height
)
2274 DisplayModePtr target_mode
= NULL
;
2275 Rotation target_rotation
= RR_Rotate_0
;
2276 DisplayModePtr default_mode
;
2277 int default_preferred
, target_preferred
= 0, o
;
2279 /* User preferred > preferred > other modes */
2280 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);) {
2281 default_mode
= xf86DefaultMode(config
->output
[o
], width
, height
);
2285 default_preferred
= (((default_mode
->type
& M_T_PREFERRED
) != 0) +
2286 ((default_mode
->type
& M_T_USERPREF
) != 0));
2288 if (default_preferred
> target_preferred
|| !target_mode
) {
2289 target_mode
= default_mode
;
2290 target_preferred
= default_preferred
;
2291 target_rotation
= config
->output
[o
]->initial_rotation
;
2292 config
->compat_output
= o
;
2297 modes
[config
->compat_output
] = target_mode
;
2299 /* Fill in other output modes */
2300 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);) {
2302 modes
[o
] = xf86ClosestMode(config
->output
[o
], target_mode
,
2303 target_rotation
, width
, height
);
2306 return target_mode
!= NULL
;
2310 xf86TargetUserpref(ScrnInfoPtr scrn
, xf86CrtcConfigPtr config
,
2311 DisplayModePtr
* modes
, Bool
*enabled
, int width
, int height
)
2315 if (xf86UserConfiguredOutputs(scrn
, modes
))
2316 return xf86TargetFallback(scrn
, config
, modes
, enabled
, width
, height
);
2318 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);)
2319 if (xf86OutputHasUserPreferredMode(config
->output
[o
]))
2321 xf86TargetFallback(scrn
, config
, modes
, enabled
, width
, height
);
2327 xf86CrtcSetInitialGamma(xf86CrtcPtr crtc
, float gamma_red
, float gamma_green
,
2331 CARD16
*red
, *green
, *blue
;
2333 red
= malloc(3 * size
* sizeof(CARD16
));
2335 blue
= green
+ size
;
2337 /* Only cause warning if user wanted gamma to be set. */
2338 if (!crtc
->funcs
->gamma_set
&&
2339 (gamma_red
!= 1.0 || gamma_green
!= 1.0 || gamma_blue
!= 1.0)) {
2343 else if (!crtc
->funcs
->gamma_set
) {
2348 /* At this early stage none of the randr-interface stuff is up.
2349 * So take the default gamma size for lack of something better.
2351 for (i
= 0; i
< size
; i
++) {
2352 if (gamma_red
== 1.0)
2355 red
[i
] = (CARD16
) (pow((double) i
/ (double) (size
- 1),
2356 1. / (double) gamma_red
) * (double) (size
-
2360 if (gamma_green
== 1.0)
2363 green
[i
] = (CARD16
) (pow((double) i
/ (double) (size
- 1),
2364 1. / (double) gamma_green
) *
2365 (double) (size
- 1) * 256);
2367 if (gamma_blue
== 1.0)
2370 blue
[i
] = (CARD16
) (pow((double) i
/ (double) (size
- 1),
2371 1. / (double) gamma_blue
) * (double) (size
-
2376 /* Default size is 256, so anything else is failure. */
2377 if (size
!= crtc
->gamma_size
) {
2382 crtc
->gamma_size
= size
;
2383 memcpy(crtc
->gamma_red
, red
, crtc
->gamma_size
* sizeof(CARD16
));
2384 memcpy(crtc
->gamma_green
, green
, crtc
->gamma_size
* sizeof(CARD16
));
2385 memcpy(crtc
->gamma_blue
, blue
, crtc
->gamma_size
* sizeof(CARD16
));
2387 /* Do not set gamma now, delay until the crtc is activated. */
2395 xf86OutputSetInitialGamma(xf86OutputPtr output
)
2397 XF86ConfMonitorPtr mon
= output
->conf_monitor
;
2398 float gamma_red
= 1.0, gamma_green
= 1.0, gamma_blue
= 1.0;
2406 /* Get configured values, where they exist. */
2407 if (mon
->mon_gamma_red
>= GAMMA_MIN
&& mon
->mon_gamma_red
<= GAMMA_MAX
)
2408 gamma_red
= mon
->mon_gamma_red
;
2410 if (mon
->mon_gamma_green
>= GAMMA_MIN
&& mon
->mon_gamma_green
<= GAMMA_MAX
)
2411 gamma_green
= mon
->mon_gamma_green
;
2413 if (mon
->mon_gamma_blue
>= GAMMA_MIN
&& mon
->mon_gamma_blue
<= GAMMA_MAX
)
2414 gamma_blue
= mon
->mon_gamma_blue
;
2416 /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */
2417 if (gamma_red
!= 1.0 || gamma_green
!= 1.0 || gamma_blue
!= 1.0) {
2418 xf86DrvMsg(output
->scrn
->scrnIndex
, X_INFO
,
2419 "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n",
2420 output
->name
, gamma_red
, gamma_green
, gamma_blue
);
2421 return xf86CrtcSetInitialGamma(output
->crtc
, gamma_red
, gamma_green
,
2429 * Construct default screen configuration
2431 * Given auto-detected (and, eventually, configured) values,
2432 * construct a usable configuration for the system
2434 * canGrow indicates that the driver can resize the screen to larger than its
2435 * initially configured size via the config->funcs->resize hook. If TRUE, this
2436 * function will set virtualX and virtualY to match the initial configuration
2437 * and leave config->max{Width,Height} alone. If FALSE, it will bloat
2438 * virtual[XY] to include the largest modes and set config->max{Width,Height}
2443 xf86InitialConfiguration(ScrnInfoPtr scrn
, Bool canGrow
)
2445 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
2448 DisplayModePtr
*modes
;
2451 int i
= scrn
->scrnIndex
;
2452 Bool have_outputs
= TRUE
;
2454 Bool success
= FALSE
;
2456 /* Set up the device options */
2457 config
->options
= xnfalloc(sizeof(xf86DeviceOptions
));
2458 memcpy(config
->options
, xf86DeviceOptions
, sizeof(xf86DeviceOptions
));
2459 xf86ProcessOptions(scrn
->scrnIndex
, scrn
->options
, config
->options
);
2460 config
->debug_modes
= xf86ReturnOptValBool(config
->options
,
2461 OPTION_MODEDEBUG
, FALSE
);
2463 if (scrn
->display
->virtualX
&& !scrn
->is_gpu
)
2464 width
= scrn
->display
->virtualX
;
2466 width
= config
->maxWidth
;
2467 if (scrn
->display
->virtualY
&& !scrn
->is_gpu
)
2468 height
= scrn
->display
->virtualY
;
2470 height
= config
->maxHeight
;
2472 xf86ProbeOutputModes(scrn
, width
, height
);
2474 crtcs
= xnfcalloc(config
->num_output
, sizeof(xf86CrtcPtr
));
2475 modes
= xnfcalloc(config
->num_output
, sizeof(DisplayModePtr
));
2476 enabled
= xnfcalloc(config
->num_output
, sizeof(Bool
));
2478 ret
= xf86CollectEnabledOutputs(scrn
, config
, enabled
);
2479 if (ret
== FALSE
&& canGrow
) {
2481 xf86DrvMsg(i
, X_WARNING
,
2482 "Unable to find connected outputs - setting %dx%d "
2483 "initial framebuffer\n",
2484 NO_OUTPUT_DEFAULT_WIDTH
, NO_OUTPUT_DEFAULT_HEIGHT
);
2485 have_outputs
= FALSE
;
2488 if (xf86TargetUserpref(scrn
, config
, modes
, enabled
, width
, height
))
2489 xf86DrvMsg(i
, X_INFO
, "Using user preference for initial modes\n");
2490 else if (xf86TargetPreferred
2491 (scrn
, config
, modes
, enabled
, width
, height
))
2492 xf86DrvMsg(i
, X_INFO
, "Using exact sizes for initial modes\n");
2493 else if (xf86TargetAspect(scrn
, config
, modes
, enabled
, width
, height
))
2494 xf86DrvMsg(i
, X_INFO
,
2495 "Using fuzzy aspect match for initial modes\n");
2496 else if (xf86TargetFallback
2497 (scrn
, config
, modes
, enabled
, width
, height
))
2498 xf86DrvMsg(i
, X_INFO
, "Using sloppy heuristic for initial modes\n");
2500 xf86DrvMsg(i
, X_WARNING
, "Unable to find initial modes\n");
2503 for (o
= -1; nextEnabledOutput(config
, enabled
, &o
);) {
2505 xf86DrvMsg(scrn
->scrnIndex
, X_ERROR
,
2506 "Output %s enabled but has no modes\n",
2507 config
->output
[o
]->name
);
2509 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
,
2510 "Output %s using initial mode %s\n",
2511 config
->output
[o
]->name
, modes
[o
]->name
);
2515 * Set the position of each output
2517 if (!xf86InitialOutputPositions(scrn
, modes
))
2521 * Set initial panning of each output
2523 xf86InitialPanning(scrn
);
2526 * Assign CRTCs to fit output configuration
2528 if (have_outputs
&& !xf86PickCrtcs(scrn
, crtcs
, modes
, 0, width
, height
))
2531 /* XXX override xf86 common frame computation code */
2533 if (!scrn
->is_gpu
) {
2534 scrn
->display
->frameX0
= 0;
2535 scrn
->display
->frameY0
= 0;
2538 for (c
= 0; c
< config
->num_crtc
; c
++) {
2539 xf86CrtcPtr crtc
= config
->crtc
[c
];
2541 crtc
->enabled
= FALSE
;
2542 memset(&crtc
->desiredMode
, '\0', sizeof(crtc
->desiredMode
));
2543 /* Set default gamma for all crtc's. */
2544 /* This is done to avoid problems later on with cloned outputs. */
2545 xf86CrtcSetInitialGamma(crtc
, 1.0, 1.0, 1.0);
2548 if (xf86_crtc_supports_gamma(scrn
))
2549 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
,
2550 "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n");
2553 * Set initial configuration
2555 for (o
= 0; o
< config
->num_output
; o
++) {
2556 xf86OutputPtr output
= config
->output
[o
];
2557 DisplayModePtr mode
= modes
[o
];
2558 xf86CrtcPtr crtc
= crtcs
[o
];
2561 xf86SaveModeContents(&crtc
->desiredMode
, mode
);
2562 crtc
->desiredRotation
= output
->initial_rotation
;
2563 crtc
->desiredX
= output
->initial_x
;
2564 crtc
->desiredY
= output
->initial_y
;
2565 crtc
->desiredTransformPresent
= FALSE
;
2566 crtc
->enabled
= TRUE
;
2567 memcpy(&crtc
->panningTotalArea
, &output
->initialTotalArea
,
2569 memcpy(&crtc
->panningTrackingArea
, &output
->initialTrackingArea
,
2571 memcpy(crtc
->panningBorder
, output
->initialBorder
,
2573 output
->crtc
= crtc
;
2574 if (!xf86OutputSetInitialGamma(output
))
2575 xf86DrvMsg(scrn
->scrnIndex
, X_WARNING
,
2576 "Initial gamma correction for output %s: failed.\n",
2580 output
->crtc
= NULL
;
2584 if (scrn
->display
->virtualX
== 0 || scrn
->is_gpu
) {
2586 * Expand virtual size to cover the current config and potential mode
2587 * switches, if the driver can't enlarge the screen later.
2589 xf86DefaultScreenLimits(scrn
, &width
, &height
, canGrow
);
2591 if (have_outputs
== FALSE
) {
2592 if (width
< NO_OUTPUT_DEFAULT_WIDTH
&&
2593 height
< NO_OUTPUT_DEFAULT_HEIGHT
) {
2594 width
= NO_OUTPUT_DEFAULT_WIDTH
;
2595 height
= NO_OUTPUT_DEFAULT_HEIGHT
;
2599 if (!scrn
->is_gpu
) {
2600 scrn
->display
->virtualX
= width
;
2601 scrn
->display
->virtualY
= height
;
2605 if (width
> scrn
->virtualX
)
2606 scrn
->virtualX
= width
;
2607 if (height
> scrn
->virtualY
)
2608 scrn
->virtualY
= height
;
2611 * Make sure the configuration isn't too small.
2613 if (width
< config
->minWidth
|| height
< config
->minHeight
)
2617 * Limit the crtc config to virtual[XY] if the driver can't grow the
2621 xf86CrtcSetSizeRange(scrn
, config
->minWidth
, config
->minHeight
,
2625 xf86SetScrnInfoModes(scrn
);
2636 * Check the CRTC we're going to map each output to vs. it's current
2637 * CRTC. If they don't match, we have to disable the output and the CRTC
2638 * since the driver will have to re-route things.
2641 xf86PrepareOutputs(ScrnInfoPtr scrn
)
2643 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
2646 for (o
= 0; o
< config
->num_output
; o
++) {
2647 xf86OutputPtr output
= config
->output
[o
];
2649 #if RANDR_GET_CRTC_INTERFACE
2650 /* Disable outputs that are unused or will be re-routed */
2651 if (!output
->funcs
->get_crtc
||
2652 output
->crtc
!= (*output
->funcs
->get_crtc
) (output
) ||
2653 output
->crtc
== NULL
)
2655 (*output
->funcs
->dpms
) (output
, DPMSModeOff
);
2660 xf86PrepareCrtcs(ScrnInfoPtr scrn
)
2662 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
2665 for (c
= 0; c
< config
->num_crtc
; c
++) {
2666 #if RANDR_GET_CRTC_INTERFACE
2667 xf86CrtcPtr crtc
= config
->crtc
[c
];
2668 xf86OutputPtr output
= NULL
;
2669 uint32_t desired_outputs
= 0, current_outputs
= 0;
2672 for (o
= 0; o
< config
->num_output
; o
++) {
2673 output
= config
->output
[o
];
2674 if (output
->crtc
== crtc
)
2675 desired_outputs
|= (1 << o
);
2676 /* If we can't tell where it's mapped, force it off */
2677 if (!output
->funcs
->get_crtc
) {
2678 desired_outputs
= 0;
2681 if ((*output
->funcs
->get_crtc
) (output
) == crtc
)
2682 current_outputs
|= (1 << o
);
2686 * If mappings are different or the CRTC is unused,
2687 * we need to disable it
2689 if (desired_outputs
!= current_outputs
|| !desired_outputs
)
2690 (*crtc
->funcs
->dpms
) (crtc
, DPMSModeOff
);
2692 (*crtc
->funcs
->dpms
) (crtc
, DPMSModeOff
);
2698 * Using the desired mode information in each crtc, set
2699 * modes (used in EnterVT functions, or at server startup)
2703 xf86SetDesiredModes(ScrnInfoPtr scrn
)
2705 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
2706 xf86CrtcPtr crtc
= config
->crtc
[0];
2707 int enabled
= 0, failed
= 0;
2710 /* A driver with this hook will take care of this */
2711 if (!crtc
->funcs
->set_mode_major
) {
2712 xf86PrepareOutputs(scrn
);
2713 xf86PrepareCrtcs(scrn
);
2716 for (c
= 0; c
< config
->num_crtc
; c
++) {
2717 xf86OutputPtr output
= NULL
;
2719 RRTransformPtr transform
;
2721 crtc
= config
->crtc
[c
];
2723 /* Skip disabled CRTCs */
2727 if (xf86CompatOutput(scrn
) && xf86CompatCrtc(scrn
) == crtc
)
2728 output
= xf86CompatOutput(scrn
);
2730 for (o
= 0; o
< config
->num_output
; o
++)
2731 if (config
->output
[o
]->crtc
== crtc
) {
2732 output
= config
->output
[o
];
2740 /* Mark that we'll need to re-set the mode for sure */
2741 memset(&crtc
->mode
, 0, sizeof(crtc
->mode
));
2742 if (!crtc
->desiredMode
.CrtcHDisplay
) {
2743 DisplayModePtr mode
=
2744 xf86OutputFindClosestMode(output
, scrn
->currentMode
);
2748 xf86SaveModeContents(&crtc
->desiredMode
, mode
);
2749 crtc
->desiredRotation
= RR_Rotate_0
;
2750 crtc
->desiredTransformPresent
= FALSE
;
2755 if (crtc
->desiredTransformPresent
)
2756 transform
= &crtc
->desiredTransform
;
2759 if (xf86CrtcSetModeTransform
2760 (crtc
, &crtc
->desiredMode
, crtc
->desiredRotation
, transform
,
2761 crtc
->desiredX
, crtc
->desiredY
)) {
2764 for (o
= 0; o
< config
->num_output
; o
++)
2765 if (config
->output
[o
]->crtc
== crtc
)
2766 config
->output
[o
]->crtc
= NULL
;
2767 crtc
->enabled
= FALSE
;
2772 xf86DisableUnusedFunctions(scrn
);
2773 return enabled
!= 0 || failed
== 0;
2777 * In the current world order, there are lists of modes per output, which may
2778 * or may not include the mode that was asked to be set by XFree86's mode
2779 * selection. Find the closest one, in the following preference order:
2782 * - Closer in size to the requested mode, but no larger
2783 * - Closer in refresh rate to the requested mode.
2787 xf86OutputFindClosestMode(xf86OutputPtr output
, DisplayModePtr desired
)
2789 DisplayModePtr best
= NULL
, scan
= NULL
;
2791 for (scan
= output
->probed_modes
; scan
!= NULL
; scan
= scan
->next
) {
2792 /* If there's an exact match, we're done. */
2793 if (xf86ModesEqual(scan
, desired
)) {
2798 /* Reject if it's larger than the desired mode. */
2799 if (scan
->HDisplay
> desired
->HDisplay
||
2800 scan
->VDisplay
> desired
->VDisplay
) {
2805 * If we haven't picked a best mode yet, use the first
2806 * one in the size range
2813 /* Find if it's closer to the right size than the current best
2816 if ((scan
->HDisplay
> best
->HDisplay
&&
2817 scan
->VDisplay
>= best
->VDisplay
) ||
2818 (scan
->HDisplay
>= best
->HDisplay
&&
2819 scan
->VDisplay
> best
->VDisplay
)) {
2824 /* Find if it's still closer to the right refresh than the current
2827 if (scan
->HDisplay
== best
->HDisplay
&&
2828 scan
->VDisplay
== best
->VDisplay
&&
2829 (fabs(scan
->VRefresh
- desired
->VRefresh
) <
2830 fabs(best
->VRefresh
- desired
->VRefresh
))) {
2838 * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
2839 * take the specified mode and apply it to the crtc connected to the compat
2840 * output. Then, find similar modes for the other outputs, as with the
2841 * InitialConfiguration code above. The goal is to clone the desired
2842 * mode across all outputs that are currently active.
2846 xf86SetSingleMode(ScrnInfoPtr pScrn
, DisplayModePtr desired
, Rotation rotation
)
2848 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
2850 xf86OutputPtr compat_output
;
2851 DisplayModePtr compat_mode
= NULL
;
2855 * Let the compat output drive the final mode selection
2857 compat_output
= xf86CompatOutput(pScrn
);
2859 compat_mode
= xf86OutputFindClosestMode(compat_output
, desired
);
2861 desired
= compat_mode
;
2863 for (c
= 0; c
< config
->num_crtc
; c
++) {
2864 xf86CrtcPtr crtc
= config
->crtc
[c
];
2865 DisplayModePtr crtc_mode
= NULL
;
2871 for (o
= 0; o
< config
->num_output
; o
++) {
2872 xf86OutputPtr output
= config
->output
[o
];
2873 DisplayModePtr output_mode
;
2875 /* skip outputs not on this crtc */
2876 if (output
->crtc
!= crtc
)
2880 output_mode
= xf86OutputFindClosestMode(output
, crtc_mode
);
2881 if (output_mode
!= crtc_mode
)
2882 output
->crtc
= NULL
;
2885 crtc_mode
= xf86OutputFindClosestMode(output
, desired
);
2888 crtc
->enabled
= FALSE
;
2891 if (!xf86CrtcSetModeTransform(crtc
, crtc_mode
, rotation
, NULL
, 0, 0))
2894 xf86SaveModeContents(&crtc
->desiredMode
, crtc_mode
);
2895 crtc
->desiredRotation
= rotation
;
2896 crtc
->desiredTransformPresent
= FALSE
;
2901 xf86DisableUnusedFunctions(pScrn
);
2902 #ifdef RANDR_12_INTERFACE
2903 xf86RandR12TellChanged(pScrn
->pScreen
);
2909 * Set the DPMS power mode of all outputs and CRTCs.
2911 * If the new mode is off, it will turn off outputs and then CRTCs.
2912 * Otherwise, it will affect CRTCs before outputs.
2915 xf86DPMSSet(ScrnInfoPtr scrn
, int mode
, int flags
)
2917 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
2923 if (mode
== DPMSModeOff
) {
2924 for (i
= 0; i
< config
->num_output
; i
++) {
2925 xf86OutputPtr output
= config
->output
[i
];
2927 if (output
->crtc
!= NULL
)
2928 (*output
->funcs
->dpms
) (output
, mode
);
2932 for (i
= 0; i
< config
->num_crtc
; i
++) {
2933 xf86CrtcPtr crtc
= config
->crtc
[i
];
2936 (*crtc
->funcs
->dpms
) (crtc
, mode
);
2939 if (mode
!= DPMSModeOff
) {
2940 for (i
= 0; i
< config
->num_output
; i
++) {
2941 xf86OutputPtr output
= config
->output
[i
];
2943 if (output
->crtc
!= NULL
)
2944 (*output
->funcs
->dpms
) (output
, mode
);
2950 * Implement the screensaver by just calling down into the driver DPMS hooks.
2952 * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
2953 * the outputs will still get disabled (blanked).
2956 xf86SaveScreen(ScreenPtr pScreen
, int mode
)
2958 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
2960 if (xf86IsUnblank(mode
))
2961 xf86DPMSSet(pScrn
, DPMSModeOn
, 0);
2963 xf86DPMSSet(pScrn
, DPMSModeOff
, 0);
2969 * Disable all inactive crtcs and outputs
2972 xf86DisableUnusedFunctions(ScrnInfoPtr pScrn
)
2974 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
2977 for (o
= 0; o
< xf86_config
->num_output
; o
++) {
2978 xf86OutputPtr output
= xf86_config
->output
[o
];
2981 (*output
->funcs
->dpms
) (output
, DPMSModeOff
);
2984 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
2985 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
2987 if (!crtc
->enabled
) {
2988 crtc
->funcs
->dpms(crtc
, DPMSModeOff
);
2989 memset(&crtc
->mode
, 0, sizeof(crtc
->mode
));
2990 xf86RotateDestroy(crtc
);
2991 crtc
->active
= FALSE
;
2995 xf86_crtc_notify(pScrn
->pScreen
);
2997 pScrn
->ModeSet(pScrn
);
3000 #ifdef RANDR_12_INTERFACE
3002 #define EDID_ATOM_NAME "EDID"
3005 * Set the RandR EDID property
3008 xf86OutputSetEDIDProperty(xf86OutputPtr output
, void *data
, int data_len
)
3010 Atom edid_atom
= MakeAtom(EDID_ATOM_NAME
, sizeof(EDID_ATOM_NAME
) - 1, TRUE
);
3012 /* This may get called before the RandR resources have been created */
3013 if (output
->randr_output
== NULL
)
3016 if (data_len
!= 0) {
3017 RRChangeOutputProperty(output
->randr_output
, edid_atom
, XA_INTEGER
, 8,
3018 PropModeReplace
, data_len
, data
, FALSE
, TRUE
);
3021 RRDeleteOutputProperty(output
->randr_output
, edid_atom
);
3027 /* Pull out a phyiscal size from a detailed timing if available. */
3028 struct det_phySize_parameter
{
3029 xf86OutputPtr output
;
3035 handle_detailed_physical_size(struct detailed_monitor_section
3036 *det_mon
, void *data
)
3038 struct det_phySize_parameter
*p
;
3040 p
= (struct det_phySize_parameter
*) data
;
3045 xf86DetTimingApplyQuirks(det_mon
, p
->quirks
,
3046 p
->output
->MonInfo
->features
.hsize
,
3047 p
->output
->MonInfo
->features
.vsize
);
3048 if (det_mon
->type
== DT
&&
3049 det_mon
->section
.d_timings
.h_size
!= 0 &&
3050 det_mon
->section
.d_timings
.v_size
!= 0) {
3051 /* some sanity checking for aspect ratio:
3052 assume any h / v (or v / h) > 2.4 to be bogus.
3053 This would even include cinemascope */
3054 if (((det_mon
->section
.d_timings
.h_size
* 5) <
3055 (det_mon
->section
.d_timings
.v_size
* 12)) &&
3056 ((det_mon
->section
.d_timings
.v_size
* 5) <
3057 (det_mon
->section
.d_timings
.h_size
* 12))) {
3058 p
->output
->mm_width
= det_mon
->section
.d_timings
.h_size
;
3059 p
->output
->mm_height
= det_mon
->section
.d_timings
.v_size
;
3062 xf86DrvMsg(p
->output
->scrn
->scrnIndex
, X_WARNING
,
3063 "Output %s: Strange aspect ratio (%i/%i), "
3064 "consider adding a quirk\n", p
->output
->name
,
3065 det_mon
->section
.d_timings
.h_size
,
3066 det_mon
->section
.d_timings
.v_size
);
3071 * Set the EDID information for the specified output
3074 xf86OutputSetEDID(xf86OutputPtr output
, xf86MonPtr edid_mon
)
3076 ScrnInfoPtr scrn
= output
->scrn
;
3077 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
3078 Bool debug_modes
= config
->debug_modes
|| xf86Initialising
;
3080 #ifdef RANDR_12_INTERFACE
3084 free(output
->MonInfo
);
3086 output
->MonInfo
= edid_mon
;
3087 output
->mm_width
= 0;
3088 output
->mm_height
= 0;
3091 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
, "EDID for output %s\n",
3093 xf86PrintEDID(edid_mon
);
3096 /* Set the DDC properties for the 'compat' output */
3097 if (output
== xf86CompatOutput(scrn
))
3098 xf86SetDDCproperties(scrn
, edid_mon
);
3100 #ifdef RANDR_12_INTERFACE
3101 /* Set the RandR output properties */
3104 if (edid_mon
->ver
.version
== 1) {
3106 if (edid_mon
->flags
& EDID_COMPLETE_RAWDATA
)
3107 size
+= edid_mon
->no_sections
* 128;
3109 else if (edid_mon
->ver
.version
== 2)
3112 xf86OutputSetEDIDProperty(output
, edid_mon
? edid_mon
->rawData
: NULL
,
3118 struct det_phySize_parameter p
;
3121 p
.quirks
= xf86DDCDetectQuirks(scrn
->scrnIndex
, edid_mon
, FALSE
);
3123 xf86ForEachDetailedBlock(edid_mon
, handle_detailed_physical_size
, &p
);
3125 /* if no mm size is available from a detailed timing, check the max size field */
3126 if ((!output
->mm_width
|| !output
->mm_height
) &&
3127 (edid_mon
->features
.hsize
&& edid_mon
->features
.vsize
)) {
3128 output
->mm_width
= edid_mon
->features
.hsize
* 10;
3129 output
->mm_height
= edid_mon
->features
.vsize
* 10;
3135 * Return the list of modes supported by the EDID information
3136 * stored in 'output'
3139 xf86OutputGetEDIDModes(xf86OutputPtr output
)
3141 ScrnInfoPtr scrn
= output
->scrn
;
3142 xf86MonPtr edid_mon
= output
->MonInfo
;
3146 return xf86DDCGetModes(scrn
->scrnIndex
, edid_mon
);
3149 /* maybe we should care about DDC1? meh. */
3151 xf86OutputGetEDID(xf86OutputPtr output
, I2CBusPtr pDDCBus
)
3153 ScrnInfoPtr scrn
= output
->scrn
;
3156 mon
= xf86DoEEDID(scrn
, pDDCBus
, TRUE
);
3158 xf86DDCApplyQuirks(scrn
->scrnIndex
, mon
);
3163 static const char *_xf86ConnectorNames
[] = {
3164 "None", "VGA", "DVI-I", "DVI-D",
3165 "DVI-A", "Composite", "S-Video",
3166 "Component", "LFP", "Proprietary",
3167 "HDMI", "DisplayPort",
3171 xf86ConnectorGetName(xf86ConnectorType connector
)
3173 return _xf86ConnectorNames
[connector
];
3177 x86_crtc_box_intersect(BoxPtr dest
, BoxPtr a
, BoxPtr b
)
3179 dest
->x1
= a
->x1
> b
->x1
? a
->x1
: b
->x1
;
3180 dest
->x2
= a
->x2
< b
->x2
? a
->x2
: b
->x2
;
3181 dest
->y1
= a
->y1
> b
->y1
? a
->y1
: b
->y1
;
3182 dest
->y2
= a
->y2
< b
->y2
? a
->y2
: b
->y2
;
3184 if (dest
->x1
>= dest
->x2
|| dest
->y1
>= dest
->y2
)
3185 dest
->x1
= dest
->x2
= dest
->y1
= dest
->y2
= 0;
3189 x86_crtc_box(xf86CrtcPtr crtc
, BoxPtr crtc_box
)
3191 if (crtc
->enabled
) {
3192 crtc_box
->x1
= crtc
->x
;
3193 crtc_box
->x2
= crtc
->x
+ xf86ModeWidth(&crtc
->mode
, crtc
->rotation
);
3194 crtc_box
->y1
= crtc
->y
;
3195 crtc_box
->y2
= crtc
->y
+ xf86ModeHeight(&crtc
->mode
, crtc
->rotation
);
3198 crtc_box
->x1
= crtc_box
->x2
= crtc_box
->y1
= crtc_box
->y2
= 0;
3202 xf86_crtc_box_area(BoxPtr box
)
3204 return (int) (box
->x2
- box
->x1
) * (int) (box
->y2
- box
->y1
);
3209 * Return the crtc covering 'box'. If two crtcs cover a portion of
3210 * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
3211 * with greater coverage
3215 xf86_covering_crtc(ScrnInfoPtr pScrn
,
3216 BoxPtr box
, xf86CrtcPtr desired
, BoxPtr crtc_box_ret
)
3218 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
3219 xf86CrtcPtr crtc
, best_crtc
;
3220 int coverage
, best_coverage
;
3222 BoxRec crtc_box
, cover_box
;
3226 crtc_box_ret
->x1
= 0;
3227 crtc_box_ret
->x2
= 0;
3228 crtc_box_ret
->y1
= 0;
3229 crtc_box_ret
->y2
= 0;
3230 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
3231 crtc
= xf86_config
->crtc
[c
];
3232 x86_crtc_box(crtc
, &crtc_box
);
3233 x86_crtc_box_intersect(&cover_box
, &crtc_box
, box
);
3234 coverage
= xf86_crtc_box_area(&cover_box
);
3235 if (coverage
&& crtc
== desired
) {
3236 *crtc_box_ret
= crtc_box
;
3239 else if (coverage
> best_coverage
) {
3240 *crtc_box_ret
= crtc_box
;
3242 best_coverage
= coverage
;
3249 * For overlay video, compute the relevant CRTC and
3250 * clip video to that.
3252 * returning FALSE means there was a memory failure of some kind,
3253 * not that the video shouldn't be displayed
3257 xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn
,
3258 xf86CrtcPtr
* crtc_ret
,
3259 xf86CrtcPtr desired_crtc
,
3264 INT32
*yb
, RegionPtr reg
, INT32 width
, INT32 height
)
3267 RegionRec crtc_region_local
;
3268 RegionPtr crtc_region
= reg
;
3272 xf86CrtcPtr crtc
= xf86_covering_crtc(pScrn
, dst
,
3277 RegionInit(&crtc_region_local
, &crtc_box
, 1);
3278 crtc_region
= &crtc_region_local
;
3279 RegionIntersect(crtc_region
, crtc_region
, reg
);
3284 ret
= xf86XVClipVideoHelper(dst
, xa
, xb
, ya
, yb
,
3285 crtc_region
, width
, height
);
3287 if (crtc_region
!= reg
)
3288 RegionUninit(&crtc_region_local
);
3294 xf86_crtc_notify_proc_ptr
3295 xf86_wrap_crtc_notify(ScreenPtr screen
, xf86_crtc_notify_proc_ptr
new)
3297 if (xf86CrtcConfigPrivateIndex
!= -1) {
3298 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
3299 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
3300 xf86_crtc_notify_proc_ptr old
;
3302 old
= config
->xf86_crtc_notify
;
3303 config
->xf86_crtc_notify
= new;
3310 xf86_unwrap_crtc_notify(ScreenPtr screen
, xf86_crtc_notify_proc_ptr old
)
3312 if (xf86CrtcConfigPrivateIndex
!= -1) {
3313 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
3314 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
3316 config
->xf86_crtc_notify
= old
;
3321 xf86_crtc_notify(ScreenPtr screen
)
3323 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
3324 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
3326 if (config
->xf86_crtc_notify
)
3327 config
->xf86_crtc_notify(screen
);
3331 xf86_crtc_supports_gamma(ScrnInfoPtr pScrn
)
3333 if (xf86CrtcConfigPrivateIndex
!= -1) {
3334 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
3337 /* for multiple drivers loaded we need this */
3340 if (xf86_config
->num_crtc
== 0)
3342 crtc
= xf86_config
->crtc
[0];
3344 return crtc
->funcs
->gamma_set
!= NULL
;
3351 xf86ProviderSetup(ScrnInfoPtr scrn
,
3352 const xf86ProviderFuncsRec
*funcs
, const char *name
)
3354 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
3356 assert(!xf86_config
->name
);
3359 xf86_config
->name
= strdup(name
);
3360 xf86_config
->provider_funcs
= funcs
;
3361 #ifdef RANDR_12_INTERFACE
3362 xf86_config
->randr_provider
= NULL
;
3367 xf86DetachAllCrtc(ScrnInfoPtr scrn
)
3369 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
3372 for (i
= 0; i
< xf86_config
->num_crtc
; i
++) {
3373 xf86CrtcPtr crtc
= xf86_config
->crtc
[i
];
3375 if (crtc
->randr_crtc
)
3376 RRCrtcDetachScanoutPixmap(crtc
->randr_crtc
);
3379 (*crtc
->funcs
->dpms
) (crtc
, DPMSModeOff
);
3380 /* force a reset the next time its used */
3381 crtc
->randr_crtc
->mode
= NULL
;
3382 crtc
->mode
.HDisplay
= 0;
3383 crtc
->x
= crtc
->y
= 0;