[Intel-gfx] [PATCH] treat disabled CRTCs as "not covering" for scanline wait purposes

Jesse Barnes jbarnes at virtuousgeek.org
Wed Jun 24 21:21:47 CEST 2009


Now that swapbuffers does a scanline wait to avoid tearing, it's
important to take into account the CRTC status to avoid hangs.  If we
do a scanline wait when the CRTC is off (due to DPMS for example) we'll
hang the GPU.  So add some code to check the CRTC DPMS status to the
i830_covering_crtc function, returning NULL if none of the covering
CRTCs are actually active.  KMS vs UMS logic is hidden in new i830*
functions, cleaning up both DRI2 & video paths a bit.

Fixes fdo bug #22383.

Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 02a71ae..8f45e84 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -71,7 +71,7 @@ typedef struct {
     int num_props;
     drmmode_prop_ptr props;
     void *private_data;
-	/* this is used to store private data */
+    int dpms_mode;
 } drmmode_output_private_rec, *drmmode_output_private_ptr;
 
 static void
@@ -727,6 +727,7 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
                                 drmmode_output->output_id,
                                 props->prop_id,
                                 mode);
+			drmmode_output->dpms_mode = mode;
                         drmModeFreeProperty(props);
                         return;
 		}
@@ -734,6 +735,14 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
 	}
 }
 
+int
+drmmode_output_dpms_status(xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+	return drmmode_output->dpms_mode;
+}
+
 static Bool
 drmmode_property_ignore(drmModePropertyPtr prop)
 {
diff --git a/src/i830.h b/src/i830.h
index 6825e77..25ed424 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -691,7 +691,10 @@ void I830DRI2CloseScreen(ScreenPtr pScreen);
 
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp);
 extern int drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
+extern int drmmode_output_dpms_status(xf86OutputPtr output);
 
+extern Bool i830_crtc_on(xf86CrtcPtr crtc);
+extern int i830_crtc_to_pipe(xf86CrtcPtr crtc);
 extern Bool I830AccelInit(ScreenPtr pScreen);
 extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
 					   int ydir, int rop,
diff --git a/src/i830_dri.c b/src/i830_dri.c
index d00b42c..be09126 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -311,12 +311,7 @@ I830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
 
 	/* Make sure the CRTC is valid and this is the real front buffer */
 	if (crtc != NULL && !crtc->rotatedData) {
-	    if (pI830->use_drm_mode)
-		pipe = drmmode_get_pipe_from_crtc_id(pI830->bufmgr, crtc);
-	    else {
-		I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-		pipe = intel_crtc->pipe;
-	    }
+	    pipe = i830_crtc_to_pipe(crtc);
 
 	    if (pipe == 0) {
 		event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 70b8788..b9b9d0b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2456,6 +2456,49 @@ i830_init_bufmgr(ScrnInfoPtr pScrn)
    }
 }
 
+Bool i830_crtc_on(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pI830->use_drm_mode) {
+	int i, active_outputs = 0;
+
+	/* Kernel manages CRTC status based out output config */
+	for (i = 0; i < xf86_config->num_output; i++) {
+	    xf86OutputPtr output = xf86_config->output[i];
+	    if (drmmode_output_dpms_status(output) == DPMSModeOn)
+		active_outputs++;
+	}
+
+	if (active_outputs)
+	    return TRUE;
+	return FALSE;
+    } else {
+	I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+	if (intel_crtc->dpms_mode == DPMSModeOn)
+	    return TRUE;
+	return FALSE;
+    }
+}
+
+int i830_crtc_to_pipe(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    int pipe;
+
+    if (pI830->use_drm_mode) {
+	pipe = drmmode_get_pipe_from_crtc_id(pI830->bufmgr, crtc);
+    } else {
+	I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+	pipe = intel_crtc->pipe;
+    }
+
+    return pipe;
+}
 
 static void
 I830AdjustMemory(ScreenPtr pScreen)
diff --git a/src/i830_video.c b/src/i830_video.c
index 1ff80a0..d543cc4 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1734,6 +1734,11 @@ i830_covering_crtc (ScrnInfoPtr pScrn,
     for (c = 0; c < xf86_config->num_crtc; c++)
     {
 	crtc = xf86_config->crtc[c];
+
+	/* If the CRTC is off, treat it as not covering */
+	if (!i830_crtc_on(crtc))
+	    continue;
+
 	i830_crtc_box (crtc, &crtc_box);
 	i830_box_intersect (&cover_box, &crtc_box, box);
 	coverage = i830_box_area (&cover_box);
@@ -2491,14 +2496,8 @@ I830PutImage(ScrnInfoPtr pScrn,
 	    int y1, y2;
 	    int pipe = -1, event, load_scan_lines_pipe;
 
-	    if (pixmap_is_scanout(pPixmap)) {
-		if (pI830->use_drm_mode)
-		    pipe = drmmode_get_pipe_from_crtc_id(pI830->bufmgr, crtc);
-		else {
-		    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-		    pipe = intel_crtc->pipe;
-		}
-	    }
+	    if (pixmap_is_scanout(pPixmap))
+		pipe = i830_crtc_to_pipe(crtc);
 
 	    if (pipe >= 0) {
 		if (pipe == 0) {



More information about the Intel-gfx mailing list