xf86-video-intel: 4 commits - src/sna/sna_display.c src/sna/sna.h src/sna/sna_present.c src/uxa/intel_display.c test/present-test.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Feb 13 11:08:29 PST 2015


 src/sna/sna.h           |    8 ++
 src/sna/sna_display.c   |   73 +++++++++++++++++-
 src/sna/sna_present.c   |  185 ++++++++++++++++++++++++++++++++++++++++++------
 src/uxa/intel_display.c |   31 --------
 test/present-test.c     |    8 ++
 5 files changed, 245 insertions(+), 60 deletions(-)

New commits:
commit 9a311f9da612ba02b24458f6a40b6a5445ad4869
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 13 14:03:16 2015 +0000

    sna: Throw away the TearFree damage if it grows too big
    
    The Damage layer is slow, so reduce the amount of work it has to do by
    explicitly throwing away any information other than the bbox.
    
    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 5b49f41..c95fe98 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1369,6 +1369,20 @@ bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
 	return RegionNil(&sna->mode.shadow_region);
 }
 
+static void sna_mode_damage(DamagePtr damage, RegionPtr region, void *closure)
+{
+	/* Throw away the rectangles if the region grows too big */
+	region = DamageRegion(damage);
+	if (region->data) {
+		RegionRec dup;
+
+		dup = *region;
+		RegionUninit(&dup);
+
+		region->data = NULL;
+	}
+}
+
 static bool sna_mode_enable_shadow(struct sna *sna)
 {
 	ScreenPtr screen = to_screen_from_sna(sna);
@@ -1378,9 +1392,9 @@ static bool sna_mode_enable_shadow(struct sna *sna)
 	assert(sna->mode.shadow_damage == NULL);
 	assert(sna->mode.shadow_active == 0);
 
-	sna->mode.shadow_damage = DamageCreate(NULL, NULL,
-					       DamageReportNone, TRUE,
-					       screen, screen);
+	sna->mode.shadow_damage = DamageCreate(sna_mode_damage, NULL,
+					       DamageReportRawRegion,
+					       TRUE, screen, sna);
 	if (!sna->mode.shadow_damage)
 		return false;
 
commit adaf0a2c6189ae0460219b9b47df54defd64011b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 13 09:13:33 2015 +0000

    sna/present: Hook into TearFree
    
    For the duration of the Present flip chain, replace our frontbuffer with
    the Client's Pixmap. Before any attempt to draw into the real
    frontbuffer, Present will unflip back to the TearFree front+shadow.
    However, it does give the Client direct access to the scanout through
    their Pixmap (effectively disabling TearFree on behalf of the Client).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index d2c95ff..1bddf7a 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -284,6 +284,7 @@ struct sna {
 		struct kgem_bo *shadow;
 		unsigned front_active;
 		unsigned shadow_active;
+		unsigned rr_active;
 		unsigned flip_active;
 		unsigned hidden;
 		bool dirty;
@@ -310,6 +311,13 @@ struct sna {
 		Bool (*rrGetInfo)(ScreenPtr, Rotation *);
 	} mode;
 
+	struct sna_tearfree {
+		struct notifier {
+			void (*func)(struct sna *, void *);
+			void *data;
+		} hook[2];
+	} tearfree;
+
 	struct {
 		struct sna_cursor *cursors;
 		xf86CursorInfoPtr info;
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 4f4ffdc..5b49f41 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1384,24 +1384,39 @@ static bool sna_mode_enable_shadow(struct sna *sna)
 	if (!sna->mode.shadow_damage)
 		return false;
 
-	DamageRegister(&sna->front->drawable, sna->mode.shadow_damage);
+	DamageRegister(&screen->GetScreenPixmap(screen)->drawable,
+		       sna->mode.shadow_damage);
 	return true;
 }
 
+inline static PixmapPtr sna_screen_pixmap(struct sna *sna)
+{
+	return to_screen_from_sna(sna)->GetScreenPixmap(to_screen_from_sna(sna));
+}
+
 static void sna_mode_disable_shadow(struct sna *sna)
 {
 	struct sna_pixmap *priv;
+	struct notifier *nb;
 
 	if (!sna->mode.shadow_damage)
 		return;
 
 	DBG(("%s\n", __FUNCTION__));
 
+	nb = &sna->tearfree.hook[0];
+	if (nb->func) {
+		nb->func(sna, nb->data);
+		nb->func = NULL;
+	}
+	assert(sna->tearfree.hook[1].func == NULL);
+
 	priv = sna_pixmap(sna->front);
 	if (priv->move_to_gpu == wait_for_shadow)
 		priv->move_to_gpu(sna, priv, 0);
 
-	DamageUnregister(&sna->front->drawable, sna->mode.shadow_damage);
+	DamageUnregister(&sna_screen_pixmap(sna)->drawable,
+			 sna->mode.shadow_damage);
 	DamageDestroy(sna->mode.shadow_damage);
 	sna->mode.shadow_damage = NULL;
 
@@ -1544,6 +1559,7 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
 		if (sna->mode.hidden) {
 			sna->mode.hidden--;
 			assert(sna->mode.hidden);
+			assert(sna->mode.front_active == 0);
 		} else {
 			assert(sna->mode.front_active);
 			sna->mode.front_active--;
@@ -1555,7 +1571,11 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
 		kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
 		sna_crtc->shadow_bo = NULL;
 	}
-	sna_crtc->transform = false;
+	if (sna_crtc->transform) {
+		assert(sna->mode.rr_active);
+		sna->mode.rr_active--;
+		sna_crtc->transform = false;
+	}
 
 	assert(!sna_crtc->shadow);
 }
@@ -1947,7 +1967,11 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 	struct sna *sna = to_sna(scrn);
 	struct kgem_bo *bo;
 
-	sna_crtc->transform = false;
+	if (sna_crtc->transform) {
+		assert(sna->mode.rr_active);
+		sna_crtc->transform = false;
+		sna->mode.rr_active--;
+	}
 	sna_crtc->rotation = RR_Rotate_0;
 
 	if (use_shadow(sna, crtc)) {
@@ -2063,6 +2087,7 @@ force_shadow:
 		sna_crtc->shadow_bo = bo;
 out_shadow:
 		sna_crtc->transform = true;
+		sna->mode.rr_active++;
 		return kgem_bo_reference(bo);
 	} else {
 		if (sna_crtc->shadow_bo) {
@@ -2394,6 +2419,12 @@ retry: /* Attach per-crtc pixmap or direct */
 
 error:
 	sna_crtc->offset = saved_offset;
+	if (sna_crtc->transform) {
+		assert(sna->mode.rr_active);
+		sna->mode.rr_active--;
+	}
+	if (saved_transform)
+		sna->mode.rr_active++;
 	sna_crtc->transform = saved_transform;
 	sna_crtc->bo = saved_bo;
 	sna_mode_discover(sna);
@@ -7076,6 +7107,14 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
 static void shadow_flip_handler(struct drm_event_vblank *e,
 				void *data)
 {
+	struct sna *sna = data;
+
+	if (sna->tearfree.hook[0].func)
+		sna->tearfree.hook[0].func(sna, sna->tearfree.hook[0].data);
+
+	sna->tearfree.hook[0] = sna->tearfree.hook[1];
+	sna->tearfree.hook[1].func = NULL;
+
 	sna_mode_redisplay(data);
 }
 
@@ -7678,6 +7717,12 @@ fixup_flip:
 			assert(old == sna->mode.shadow);
 			assert(old->refcnt >= 1);
 			set_shadow(sna, region);
+		} else {
+			if (sna->tearfree.hook[0].func) {
+				sna->tearfree.hook[0].func(sna, sna->tearfree.hook[0].data);
+				sna->tearfree.hook[0].func = NULL;
+			}
+			assert(sna->tearfree.hook[1].func == NULL);
 		}
 	} else
 		kgem_submit(&sna->kgem);
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index 0f507b5..6cc9c2e 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -245,6 +245,11 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 	swap = sna_crtc_last_swap(crtc->devPrivate);
 	assert((int64_t)(msc - swap->msc) >= 0);
 	if ((int64_t)(msc - swap->msc) <= 0) {
+		DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
+		     pipe_from_crtc(crtc),
+		     swap->tv_sec, swap->tv_usec,
+		     (long long)swap->msc, (long long)msc,
+		     (long long)event_id));
 		present_event_notify(event_id, swap_ust(swap), swap->msc);
 		return Success;
 	}
@@ -310,8 +315,8 @@ check_flip__crtc(struct sna *sna,
 		return FALSE;
 	}
 
-	if (sna->mode.shadow_active) {
-		DBG(("%s: shadow buffer active\n", __FUNCTION__));
+	if (sna->mode.rr_active) {
+		DBG(("%s: RandR transformation active\n", __FUNCTION__));
 		return false;
 	}
 
@@ -375,11 +380,11 @@ sna_present_check_flip(RRCrtcPtr crtc,
 }
 
 static Bool
-page_flip__async(struct sna *sna,
-		 RRCrtcPtr crtc,
-		 uint64_t event_id,
-		 uint64_t target_msc,
-		 struct kgem_bo *bo)
+flip__async(struct sna *sna,
+	    RRCrtcPtr crtc,
+	    uint64_t event_id,
+	    uint64_t target_msc,
+	    struct kgem_bo *bo)
 {
 	DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
 	     __FUNCTION__,
@@ -435,11 +440,11 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
 }
 
 static Bool
-page_flip(struct sna *sna,
-	  RRCrtcPtr crtc,
-	  uint64_t event_id,
-	  uint64_t target_msc,
-	  struct kgem_bo *bo)
+flip(struct sna *sna,
+     RRCrtcPtr crtc,
+     uint64_t event_id,
+     uint64_t target_msc,
+     struct kgem_bo *bo)
 {
 	struct sna_present_event *info;
 
@@ -475,7 +480,7 @@ get_flip_bo(PixmapPtr pixmap)
 
 	DBG(("%s(pixmap=%ld)\n", __FUNCTION__, pixmap->drawable.serialNumber));
 
-	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | __MOVE_FORCE);
+	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | __MOVE_SCANOUT | __MOVE_FORCE);
 	if (priv == NULL) {
 		DBG(("%s: cannot force pixmap to the GPU\n", __FUNCTION__));
 		return NULL;
@@ -498,6 +503,130 @@ get_flip_bo(PixmapPtr pixmap)
 	return priv->gpu_bo;
 }
 
+static bool set_front(struct sna *sna, PixmapPtr pixmap)
+{
+	RegionRec *damage;
+
+	DBG(("%s: pixmap=%ld\n", __FUNCTION__, pixmap->drawable.serialNumber));
+
+	if (pixmap == sna->front)
+		return false;
+
+	sna_pixmap_discard_shadow_damage(sna_pixmap(sna->front), NULL);
+	sna->front = pixmap;
+
+	/* We rely on unflip restoring the real front before any drawing */
+	damage = DamageRegion(sna->mode.shadow_damage);
+	RegionUninit(damage);
+	damage->extents.x1 = 0;
+	damage->extents.y1 = 0;
+	damage->extents.x2 = pixmap->drawable.width;
+	damage->extents.y2 = pixmap->drawable.height;
+	damage->data = NULL;
+
+	return true;
+}
+
+static void
+xchg_handler(struct sna *sna, void *data)
+{
+	struct sna_present_event *info = data;
+	const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
+
+	DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
+	     sna_crtc_to_pipe(info->crtc),
+	     swap->tv_sec, swap->tv_usec,
+	     (long long)swap->msc,
+	     (long long)info->target_msc, (long long)info->event_id));
+	present_event_notify(info->event_id, swap_ust(swap), swap->msc);
+	free(info);
+}
+
+static Bool
+xchg(struct sna *sna,
+     RRCrtcPtr crtc,
+     uint64_t event_id,
+     uint64_t target_msc,
+     PixmapPtr pixmap,
+     Bool sync_flip)
+{
+	struct sna_present_event *info;
+	bool queued;
+
+	DBG(("%s(pipe=%d, event=%lld, sync_flip=%d)\n",
+	     __FUNCTION__,
+	     pipe_from_crtc(crtc),
+	     (long long)event_id,
+	     sync_flip));
+
+	assert(sna->flags & SNA_TEAR_FREE);
+	assert(sna->mode.shadow_damage);
+	assert(sna_pixmap(pixmap) && sna_pixmap(pixmap)->gpu_bo);
+
+	/* This effectively disables TearFree giving the client direct
+	 * access into the scanout with their Pixmap.
+	 */
+	queued = set_front(sna, pixmap);
+
+	if (!sync_flip)
+		goto notify; /* XXX We will claim that the scanout is idle */
+
+	info = malloc(sizeof(struct sna_present_event));
+	if (info == NULL)
+		return BadAlloc;
+
+	info->crtc = crtc->devPrivate;
+	info->sna = sna;
+	info->target_msc = target_msc;
+	info->event_id = event_id;
+
+	if (queued) {
+		struct notifier *nb;
+
+		nb = &sna->tearfree.hook[0];
+		if (nb->func)
+			nb++;
+		if (nb->func) {
+			DBG(("%s: executing existing notifier\n", __FUNCTION__));
+			nb->func(sna, nb->data);
+		}
+		DBG(("%s: queueing tearfree notifier: sequence %d\n",
+		     __FUNCTION__, nb - &sna->tearfree.hook[0]));
+		nb->func = xchg_handler;
+		nb->data = info;
+	} else {
+		union drm_wait_vblank vbl;
+
+		DBG(("%s: queueing vblank notifier\n", __FUNCTION__));
+
+		VG_CLEAR(vbl);
+		vbl.request.type =
+			DRM_VBLANK_ABSOLUTE |
+			DRM_VBLANK_EVENT |
+			DRM_VBLANK_NEXTONMISS;
+		vbl.request.sequence = target_msc;
+		vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
+		if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(info->crtc))) {
+			DBG(("%s: vblank enqueue failed\n", __FUNCTION__));
+			if (!sna_fake_vblank(info)) {
+				free(info);
+				goto notify;
+			}
+		}
+	}
+
+	return TRUE;
+
+notify:
+	DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
+	     pipe_from_crtc(crtc),
+	     gettime_ust64() / 1000000, gettime_ust64() % 1000000,
+	     (long long)sna_crtc_last_swap(crtc->devPrivate)->msc,
+	     (long long)target_msc, (long long)event_id));
+	present_event_notify(event_id, gettime_ust64(), target_msc);
+	return TRUE;
+}
+
 static Bool
 sna_present_flip(RRCrtcPtr crtc,
 		 uint64_t event_id,
@@ -520,11 +649,6 @@ sna_present_flip(RRCrtcPtr crtc,
 		return FALSE;
 	}
 
-	if (sna->mode.flip_active) {
-		DBG(("%s: flips still pending\n", __FUNCTION__));
-		return false;
-	}
-
 	assert(sna->present.unflip == 0);
 
 	bo = get_flip_bo(pixmap);
@@ -533,10 +657,18 @@ sna_present_flip(RRCrtcPtr crtc,
 		return FALSE;
 	}
 
+	if (sna->flags & SNA_TEAR_FREE)
+		return xchg(sna, crtc, event_id, target_msc, pixmap, sync_flip);
+
+	if (sna->mode.flip_active) {
+		DBG(("%s: flips still pending\n", __FUNCTION__));
+		return false;
+	}
+
 	if (sync_flip)
-		return page_flip(sna, crtc, event_id, target_msc, bo);
+		return flip(sna, crtc, event_id, target_msc, bo);
 	else
-		return page_flip__async(sna, crtc, event_id, target_msc, bo);
+		return flip__async(sna, crtc, event_id, target_msc, bo);
 }
 
 static void
@@ -546,7 +678,7 @@ sna_present_unflip(ScreenPtr screen, uint64_t event_id)
 	struct kgem_bo *bo;
 
 	DBG(("%s(event=%lld)\n", __FUNCTION__, (long long)event_id));
-	if (sna->mode.front_active == 0 || sna->mode.shadow_active) {
+	if (sna->mode.front_active == 0 || sna->mode.rr_active) {
 		const struct ust_msc *swap;
 
 		DBG(("%s: no CRTC active, perform no-op flip\n", __FUNCTION__));
@@ -561,6 +693,11 @@ notify:
 		return;
 	}
 
+	if (sna->flags & SNA_TEAR_FREE) {
+		set_front(sna, screen->GetScreenPixmap(screen));
+		goto notify;
+	}
+
 	if (sna->mode.flip_active) {
 		DBG(("%s: %d outstanding flips, queueing unflip\n", __FUNCTION__, sna->mode.flip_active));
 		assert(sna->present.unflip == 0);
@@ -578,11 +715,11 @@ reset_mode:
 
 	if (sna->flags & SNA_HAS_ASYNC_FLIP) {
 		DBG(("%s: trying async flip restore\n", __FUNCTION__));
-		if (page_flip__async(sna, NULL, event_id, 0, bo))
+		if (flip__async(sna, NULL, event_id, 0, bo))
 			return;
 	}
 
-	if (!page_flip(sna, NULL, event_id, 0, bo))
+	if (!flip(sna, NULL, event_id, 0, bo))
 		goto reset_mode;
 }
 
@@ -603,6 +740,8 @@ static present_screen_info_rec present_info = {
 
 bool sna_present_open(struct sna *sna, ScreenPtr screen)
 {
+	DBG(("%s(num_crtc=%d)\n", __FUNCTION__, sna->mode.num_real_crtc));
+
 	if (sna->mode.num_real_crtc == 0)
 		return false;
 
commit 42ebe2ef9646be5c4586868cf332b4cd79bb4618
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 13 08:06:43 2015 +0000

    uxa: Remove the filtering of bogus Present MSC values
    
    If the intention was to filter the return values from the kernel, the
    filtering would have been applied to the kernel values and not to the
    incoming values from Present. This filtering introduces crazy integer
    promotion and truncation bugs all because Present feeds garbage into its
    vblank requests.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
index 83d20c8..45afbae 100644
--- a/src/uxa/intel_display.c
+++ b/src/uxa/intel_display.c
@@ -116,7 +116,6 @@ struct intel_crtc {
 	struct list link;
 	PixmapPtr scanout_pixmap;
 	uint32_t scanout_fb_id;
-	int32_t vblank_offset;
 	uint32_t msc_prev;
 	uint64_t msc_high;
 };
@@ -1914,7 +1913,6 @@ intel_sequence_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence)
 {
 	struct intel_crtc *intel_crtc = crtc->driver_private;
 
-        sequence += intel_crtc->vblank_offset;
         if ((int32_t) (sequence - intel_crtc->msc_prev) < -0x40000000)
                 intel_crtc->msc_high += 0x100000000L;
         intel_crtc->msc_prev = sequence;
@@ -1938,37 +1936,10 @@ intel_get_crtc_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t *msc, uint64
         return 0;
 }
 
-/*
- * Convert a 64-bit adjusted MSC value into a 32-bit kernel sequence number,
- * removing the high 32 bits and subtracting out the vblank_offset term.
- *
- * This also updates the vblank_offset when it notices that the value should
- * change.
- */
-
-#define MAX_VBLANK_OFFSET       1000
-
 uint32_t
 intel_crtc_msc_to_sequence(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t expect)
 {
-	struct intel_crtc *intel_crtc = crtc->driver_private;
-        uint64_t msc, ust;
-
-	if (intel_get_crtc_msc_ust(scrn, crtc, &msc, &ust) == 0) {
-		int64_t diff = expect - msc;
-
-		/* We're way off here, assume that the kernel has lost its mind
-		 * and smack the vblank back to something sensible
-		 */
-		if (diff < -MAX_VBLANK_OFFSET || diff > MAX_VBLANK_OFFSET) {
-			intel_crtc->vblank_offset += (int32_t) diff;
-			if (intel_crtc->vblank_offset > -MAX_VBLANK_OFFSET &&
-			    intel_crtc->vblank_offset < MAX_VBLANK_OFFSET)
-				intel_crtc->vblank_offset = 0;
-		}
-	}
-
-        return (uint32_t) (expect - intel_crtc->vblank_offset);
+        return (uint32_t)expect;
 }
 
 /*
commit 35ab0afd04c3d526a26b2ef0d937c25d7eead506
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Feb 12 21:10:25 2015 +0000

    test/present: Automatically disable DPMS
    
    DPMS plays havoc with Present timings, make sure the screen doesn't turn
    off.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-test.c b/test/present-test.c
index ec8db6b..651df4a 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -31,6 +31,7 @@
 #include <X11/xshmfence.h>
 #include <X11/Xutil.h>
 #include <X11/Xlibint.h>
+#include <X11/extensions/dpms.h>
 #include <X11/extensions/randr.h>
 #include <X11/extensions/Xrandr.h>
 #include <X11/extensions/Xrender.h>
@@ -220,6 +221,7 @@ static void teardown_msc(Display *dpy, void *q)
 {
 	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
 }
+
 static int test_whole(Display *dpy)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -1344,6 +1346,7 @@ int main(void)
 {
 	Display *dpy;
 	Window root;
+	int dummy;
 	int error = 0;
 	uint64_t last_msc;
 	void *queue;
@@ -1355,6 +1358,9 @@ int main(void)
 	if (!has_present(dpy))
 		return 77;
 
+	if (DPMSQueryExtension(dpy, &dummy, &dummy))
+		DPMSDisable(dpy);
+
 	root = DefaultRootWindow(dpy);
 
 	signal(SIGALRM, SIG_IGN);
@@ -1392,5 +1398,7 @@ int main(void)
 
 	teardown_msc(dpy, queue);
 
+	if (DPMSQueryExtension(dpy, &dummy, &dummy))
+		DPMSEnable(dpy);
 	return !!error;
 }


More information about the xorg-commit mailing list