On Monday, March 17, 2008 12:11 pm Keith Packard wrote: > On Mon, 2008-03-17 at 11:17 -0700, Jesse Barnes wrote: > > So the server part of this patchset adds a new callback, ->get_crtc, to > > the xf86OutputFuncs structure. The new xf86GetCurrentConfig routine uses > > this callback to build an accurate picture of which CRTCs are mapped to > > which outputs (or NULL if the output is currently disabled) and which > > outputs are currently active. The call to xf86GetCurrentConfig replaces > > the output & CRTC DPMS off calls, which eliminates one set of flicker > > from the startup & VT switch code paths. > > This won't work -- you're assuming that the crtcs that the desired > initial configuration will match the crtc/output mapping present in the > hardware before the X server starts. > > The underlying assumption that the driver makes is that all mode setting > operations affect only the target crtc and outputs. However, if any of > those outputs are currently being driven by another crtc, the output > must be taken away from that crtc (and that other crtc turned off) > before the output can be assigned to new crtc. If you fail to observe > this protocol, you will lock up machines. Yeah, I got mixed up between how output->crtc was used. xf86InitialConfiguration sets it to what the CRTC mapping *will* be, but other code made me think it was using it purely as a "current configuration" type variable. > So, what you want to do in xf86SetDesiredModes is just turn off all > outputs and crtcs which are not hooked up the way the server will set > them up. For outputs, I think that's fairly straightforward; just > DPMSModeOff whenever the output->crtc != output->funcs->get_crtc > (output). For crtcs, you want to turn them off if no output is going to > use them, or if the set of outputs using a crtc changes. Something like the attached patch? > The goal here should be to eliminate flashing when you're not switching > the output/crtc configuration, and to make sure things work reliably > when you are. We might be able to reduce flashing when you are switching > configuration around, but that's not supposed to happen very often, > especially once we have kernel mode setting that sets the desired mode > when the system is booted. Right, once this is working right I'll need to port it to the kernel along with some other flicker reduction stuff there. Thanks, Jesse
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 6b845b7..a4f9d18 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -2034,6 +2034,56 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) } /* + * Check the CRTC we're going to map each output to vs. it's current + * CRTC. If they don't match, we have to disable the output and the CRTC + * since the driver will have to re-route things. + */ +static void +xf86PrepareOutputs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr output = config->output[o]; +#if RANDR_GET_CRTC_INTERFACE + if (output->crtc != (*output->funcs->get_crtc)(output)) +#endif + (*output->funcs->dpms)(output, DPMSModeOff); + } +} + +static void +xf86PrepareCrtcs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + for (c = 0; c < config->num_crtc; c++) { +#if RANDR_GET_CRTC_INTERFACE + xf86CrtcPtr crtc = config->crtc[c]; + xf86OutputPtr output = NULL; + uint32_t desired_outputs = 0, current_outputs = 0; + int o; + + for (o = 0; o < config->num_output; o++) { + output = config->output[o]; + if (output->crtc == crtc) + desired_outputs |= (1<<o); + if ((*output->funcs->get_crtc)(output) == crtc) + current_outputs |= (1<<o); + } + + /* If mappings are different, we need to disable it */ + if (desired_outputs != current_outputs) + (*crtc->funcs->dpms)(crtc, DPMSModeOff); +#else + (*crtc->funcs->dpms)(crtc, DPMSModeOff); +#endif + } +} + +/* * Using the desired mode information in each crtc, set * modes (used in EnterVT functions, or at server startup) */ @@ -2042,26 +2092,11 @@ _X_EXPORT Bool xf86SetDesiredModes (ScrnInfoPtr scrn) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - - /* - * Turn off everything so mode setting is done - * with hardware in a consistent state - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - (*output->funcs->dpms)(output, DPMSModeOff); - } + int c; - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; + xf86PrepareOutputs(scrn); + xf86PrepareCrtcs(scrn); - crtc->funcs->dpms(crtc, DPMSModeOff); - memset(&crtc->mode, 0, sizeof(crtc->mode)); - } - for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h index a542e7f..2d723a5 100644 --- a/hw/xfree86/modes/xf86Crtc.h +++ b/hw/xfree86/modes/xf86Crtc.h @@ -425,6 +425,13 @@ typedef struct _xf86OutputFuncs { (*get_property)(xf86OutputPtr output, Atom property); #endif +#ifdef RANDR_GET_CRTC_INTERFACE + /** + * Callback to get current CRTC for a given output + */ + xf86CrtcPtr + (*get_crtc)(xf86OutputPtr output); +#endif /** * Clean up driver-specific bits of the output */ diff --git a/randr/randrstr.h b/randr/randrstr.h index 4d7c9cc..62d4bbf 100644 --- a/randr/randrstr.h +++ b/randr/randrstr.h @@ -55,6 +55,7 @@ #define RANDR_10_INTERFACE 1 #define RANDR_12_INTERFACE 1 #define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */ +#define RANDR_GET_CRTC_INTERFACE 1 #define RANDR_INTERFACE_VERSION 0x0103
_______________________________________________ xorg mailing list xorg@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/xorg