xf86-video-intel: 2 commits - src/sna/sna_display.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Sep 9 12:59:36 PDT 2015


 src/sna/sna_display.c |  166 +++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 143 insertions(+), 23 deletions(-)

New commits:
commit d50d336605e9be7280529b0eb565402d7646c913
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 9 20:44:42 2015 +0100

    sna: Coldplug all outputs on startup
    
    Since we only update the mode list when the user queries xrandr or upon
    a hotplug event, queue a deferred probe for 2s after X starts in order
    to fill in the unknown modes.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index d82585b..d75d282 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -90,6 +90,8 @@ void *alloca(size_t);
 #include <memcheck.h>
 #endif
 
+#define COLDPLUG_DELAY_MS 2000
+
 /* Minor discrepancy between 32-bit/64-bit ABI in old kernels */
 union compat_mode_get_connector{
 	struct drm_mode_get_connector conn;
@@ -4836,8 +4838,13 @@ skip: ;
 	return out;
 }
 
-static void update_modes(xf86OutputPtr output)
+static void output_update_modes(xf86OutputPtr output)
 {
+	DBG(("%s: updating modes on output %s (id=%d): status=%d\n",
+	     __FUNCTION__, output->name, sna_output->id,
+	     sna_output->serial, serial, output->status));
+	RROutputChanged(output->randr_output, TRUE);
+
 	while (output->probed_modes)
 		xf86DeleteMode(&output->probed_modes, output->probed_modes);
 
@@ -4859,6 +4866,33 @@ static void update_modes(xf86OutputPtr output)
 	output->probed_modes = sort_modes(output->probed_modes);
 }
 
+static bool output_set_status(xf86OutputPtr output, xf86OutputStatus status)
+{
+	unsigned value;
+
+	if (status == output->status)
+		return false;
+
+	DBG(("%s: output %s (id=%d), changed status %d -> %d\n",
+	     __FUNCTION__, output->name, sna_output->id, output->status, status));
+
+	output->status = status;
+	switch (status) {
+	case XF86OutputStatusConnected:
+		value = RR_Connected;
+		break;
+	case XF86OutputStatusDisconnected:
+		value = RR_Disconnected;
+		break;
+	default:
+	case XF86OutputStatusUnknown:
+		value = RR_UnknownConnection;
+		break;
+	}
+	RROutputSetConnection(output->randr_output, value);
+	return true;
+}
+
 void sna_mode_discover(struct sna *sna)
 {
 	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
@@ -4920,30 +4954,9 @@ void sna_mode_discover(struct sna *sna)
 
 		sna_output->last_detect = 0;
 		if (sna_output->serial == serial) {
-			xf86OutputStatus status = sna_output_detect(output);
-			if (status != output->status) {
-				RROutputPtr rr = output->randr_output;
-				unsigned value;
-
-				DBG(("%s: output %s (id=%d), changed status %d -> %d\n",
-				     __FUNCTION__, output->name, sna_output->id, output->status, status));
-
-				output->status = status;
-				switch (status) {
-				case XF86OutputStatusConnected:
-					value = RR_Connected;
-					break;
-				case XF86OutputStatusDisconnected:
-					value = RR_Disconnected;
-					break;
-				default:
-				case XF86OutputStatusUnknown:
-					value = RR_UnknownConnection;
-					break;
-				}
-				RROutputSetConnection(rr, value);
-				update_modes(output);
-			}
+			if (output_set_status(output,
+					      sna_output_detect(output)))
+			    output_update_modes(output);
 			continue;
 		}
 
@@ -4978,6 +4991,39 @@ void sna_mode_discover(struct sna *sna)
 	RRTellChanged(screen);
 }
 
+/* Since we only probe the current mode on startup, we may not have the full
+ * list of modes available until the user explicitly requests them. Fake a
+ * hotplug event after a second after starting to fill in any missing modes.
+ */
+static CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data)
+{
+	struct sna *sna = data;
+	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	DBG(("%s()\n", __FUNCTION__));
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		struct sna_output *sna_output = to_sna_output(output);
+
+		if (sna_output->id == 0)
+			continue;
+		if (sna_output->last_detect)
+			continue;
+		if (output->status != XF86OutputStatusConnected)
+			continue;
+
+		output_set_status(output, sna_output_detect(output));
+		output_update_modes(output);
+	}
+
+	RRTellChanged(screen);
+	free(timer);
+	return 0;
+}
+
 static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
 {
 	struct sna_pixmap *old_priv, *new_priv;
@@ -6912,6 +6958,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
 		}
 	}
 	sort_config_outputs(sna);
+	TimerSet(NULL, 0, COLDPLUG_DELAY_MS, sna_mode_coldplug, sna);
 
 	sna_setup_provider(scrn);
 	return scrn->modes != NULL;
commit f384af433cbb39ad74e02b10d3700e71c8668506
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 9 20:28:19 2015 +0100

    sna: Hook up kernel modes on hotplug notification
    
    Some display managers, for example mutter, only use
    XRRScreenResourcesCurrent() which means they only query the existing
    modes on an output. We need to therefore update the list of available
    modes after a hotplug event.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index d13d283..d82585b 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -4787,6 +4787,78 @@ static bool disable_unused_crtc(struct sna *sna)
 	return update;
 }
 
+static int modecmp(DisplayModePtr a, DisplayModePtr b)
+{
+	int diff;
+
+	diff = (b->type & M_T_PREFERRED)- (a->type & M_T_PREFERRED);
+	if (diff)
+		return diff;
+
+	diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
+	if (diff)
+		return diff;
+
+	return b->Clock - a->Clock;
+}
+
+static DisplayModePtr sort_modes(DisplayModePtr in)
+{
+	DisplayModePtr out = NULL, i, o, *op, prev;
+
+	/* sort by preferred status and pixel area */
+	while (in) {
+		i = in;
+		in = in->next;
+		for (op = &out; (o = *op); op = &o->next) {
+			int ret = modecmp(o, i);
+			if (ret > 0)
+				break;
+			if (ret < 0)
+				continue;
+			if (!strcmp(o->name, i->name) && xf86ModesEqual(o, i)) {
+				free((void *)i->name);
+				free(i);
+				goto skip;
+			}
+		}
+		i->next = *op;
+		*op = i;
+skip: ;
+	}
+
+	/* hook up backward links */
+	prev = NULL;
+	for (o = out; o; o = o->next) {
+		o->prev = prev;
+		prev = o;
+	}
+	return out;
+}
+
+static void update_modes(xf86OutputPtr output)
+{
+	while (output->probed_modes)
+		xf86DeleteMode(&output->probed_modes, output->probed_modes);
+
+	if (output->status != XF86OutputStatusConnected)
+		return;
+
+	output->probed_modes = NULL;
+
+	if (output->conf_monitor)
+		output->probed_modes =
+			xf86ModesAdd(output->probed_modes,
+				     xf86GetMonitorModes(output->scrn,
+							 output->conf_monitor));
+
+	output->probed_modes =
+		xf86ModesAdd(output->probed_modes,
+			     output->funcs->get_modes(output));
+
+	output->probed_modes = sort_modes(output->probed_modes);
+}
+
 void sna_mode_discover(struct sna *sna)
 {
 	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
@@ -4870,6 +4942,7 @@ void sna_mode_discover(struct sna *sna)
 					break;
 				}
 				RROutputSetConnection(rr, value);
+				update_modes(output);
 			}
 			continue;
 		}


More information about the xorg-commit mailing list