summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-06-24 13:12:25 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-24 13:13:07 -0700
commit5d80e24b5fc6d6028028da6ded35389c08bfce29 (patch)
tree02571f6b3270a0fe8297f2bd590bd9c8c9bce64f
parent6d025e679a99778496576af9a6a6fa8c043ae811 (diff)
Treat disabled CRTCs as "not covering" for scanline wait purposes
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@virtuousgeek.org>
-rw-r--r--src/drmmode_display.c11
-rw-r--r--src/i830.h3
-rw-r--r--src/i830_dri.c7
-rw-r--r--src/i830_driver.c43
-rw-r--r--src/i830_video.c15
5 files changed, 64 insertions, 15 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 02a71ae0..8f45e84e 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 6825e77e..25ed424e 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 d00b42c8..be09126b 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 70b87887..b9b9d0bd 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 1ff80a05..d543cc44 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) {