xf86-video-intel: src/sna/sna_dri2.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Jun 12 04:51:07 PDT 2015


 src/sna/sna_dri2.c |  147 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 79 insertions(+), 68 deletions(-)

New commits:
commit b6a635baf3a2aefd8ae613ba9046222ba7911dfa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jun 12 12:46:38 2015 +0100

    sna/dri2: Move the backbuffer cache from the event chain to the window
    
    We still only keep it alive whilst the event chain is in progress, but
    moving the cache onto the window allows us to reuse it easily for triple
    buffer window swaps as well as full screen flips.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index f1c0491..5ad33fd 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -132,7 +132,6 @@ struct sna_dri2_event {
 
 	struct sna_dri2_event *chain;
 
-	struct list cache;
 	struct list link;
 
 	int flip_continue;
@@ -182,23 +181,41 @@ static int front_pitch(DrawablePtr draw)
 	return buffer ? buffer->pitch : 0;
 }
 
+struct dri2_window {
+	DRI2BufferPtr front;
+	struct sna_dri2_event *chain;
+	xf86CrtcPtr crtc;
+	int64_t msc_delta;
+	struct list cache;
+};
+
+static struct dri2_window *dri2_window(WindowPtr win)
+{
+	assert(win->drawable.type != DRAWABLE_PIXMAP);
+	return ((void **)__get_private(win, sna_window_key))[1];
+}
+
+
 static void
 sna_dri2_get_back(struct sna *sna,
 		  DrawablePtr draw,
-		  DRI2BufferPtr back,
-		  struct sna_dri2_event *info)
+		  DRI2BufferPtr back)
 {
+	struct dri2_window *priv = dri2_window((WindowPtr)draw);
 	struct kgem_bo *bo;
+	struct dri_bo *c;
 	uint32_t name;
 	int flags;
 	bool reuse;
 
-	DBG(("%s: draw size=%dx%d, back buffer handle=%d size=%dx%d, is-scanout? %d, pitch=%d, front pitch=%d, has-cache?=%d\n",
+	DBG(("%s: draw size=%dx%d, back buffer handle=%d size=%dx%d, is-scanout? %d, pitch=%d, front pitch=%d\n",
 	     __FUNCTION__, draw->width, draw->height,
 	     get_private(back)->bo->handle,
 	     get_private(back)->size & 0xffff, get_private(back)->size >> 16,
 	     get_private(back)->bo->scanout,
-	     back->pitch, front_pitch(draw), info!=NULL));
+	     back->pitch, front_pitch(draw)));
+	assert(priv);
+
 	reuse = (draw->height << 16 | draw->width) == get_private(back)->size;
 	if (reuse && get_private(back)->bo->scanout)
 		reuse = front_pitch(draw) == back->pitch;
@@ -216,20 +233,17 @@ sna_dri2_get_back(struct sna *sna,
 	}
 
 	bo = NULL;
-	if (info) {
-		struct dri_bo *c;
-		list_for_each_entry(c, &info->cache, link) {
-			DBG(("%s: cache: handle=%d, active=%d\n",
-			     __FUNCTION__, c->bo ? c->bo->handle : 0, c->bo ? c->bo->active_scanout : -1));
-			if (c->bo && c->bo->active_scanout == 0) {
-				bo = c->bo;
-				name = c->name;
-				flags = c->flags;
-				DBG(("%s: reuse cache handle=%d, name=%d, flags=%d\n", __FUNCTION__, bo->handle, name, flags));
-				list_move_tail(&c->link, &info->cache);
-				c->bo = NULL;
-				break;
-			}
+	list_for_each_entry(c, &priv->cache, link) {
+		DBG(("%s: cache: handle=%d, active=%d\n",
+		     __FUNCTION__, c->bo ? c->bo->handle : 0, c->bo ? c->bo->active_scanout : -1));
+		if (c->bo && c->bo->active_scanout == 0) {
+			bo = c->bo;
+			name = c->name;
+			flags = c->flags;
+			DBG(("%s: reuse cache handle=%d, name=%d, flags=%d\n", __FUNCTION__, bo->handle, name, flags));
+			list_move_tail(&c->link, &priv->cache);
+			c->bo = NULL;
+			break;
 		}
 	}
 	if (bo == NULL) {
@@ -266,11 +280,10 @@ sna_dri2_get_back(struct sna *sna,
 	}
 	assert(bo->active_scanout == 0);
 
-	if (info && reuse) {
+	if (reuse) {
 		bool found = false;
-		struct dri_bo *c;
 
-		list_for_each_entry_reverse(c, &info->cache, link) {
+		list_for_each_entry_reverse(c, &priv->cache, link) {
 			if (c->bo == NULL) {
 				found = true;
 				_list_del(&c->link);
@@ -283,7 +296,7 @@ sna_dri2_get_back(struct sna *sna,
 			c->bo = ref(get_private(back)->bo);
 			c->name = back->name;
 			c->flags = back->flags;
-			list_add(&c->link, &info->cache);
+			list_add(&c->link, &priv->cache);
 			DBG(("%s: cacheing handle=%d (name=%d, flags=%d, active_scanout=%d)\n", __FUNCTION__, c->bo->handle, c->name, c->flags, c->bo->active_scanout));
 		}
 	}
@@ -304,19 +317,6 @@ sna_dri2_get_back(struct sna *sna,
 	get_private(back)->stale = false;
 }
 
-struct dri2_window {
-	DRI2BufferPtr front;
-	struct sna_dri2_event *chain;
-	xf86CrtcPtr crtc;
-	int64_t msc_delta;
-};
-
-static struct dri2_window *dri2_window(WindowPtr win)
-{
-	assert(win->drawable.type != DRAWABLE_PIXMAP);
-	return ((void **)__get_private(win, sna_window_key))[1];
-}
-
 static struct sna_dri2_event *
 dri2_chain(DrawablePtr d)
 {
@@ -390,7 +390,7 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
 	if (buffer->attachment == DRI2BufferBackLeft &&
 	    draw->type != DRAWABLE_PIXMAP) {
 		DBG(("%s: replacing back buffer on window %ld\n", __FUNCTION__, draw->id));
-		sna_dri2_get_back(to_sna_from_drawable(draw), draw, buffer, dri2_chain(draw));
+		sna_dri2_get_back(to_sna_from_drawable(draw), draw, buffer);
 		assert(get_private(buffer)->bo->refcnt);
 		assert(get_private(buffer)->bo->active_scanout == 0);
 		assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
@@ -1345,6 +1345,7 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
 			priv->crtc = crtc;
 			priv->msc_delta = 0;
 			priv->chain = NULL;
+			list_init(&priv->cache);
 			dri2_window_attach((WindowPtr)draw, priv);
 		}
 	} else {
@@ -1401,17 +1402,31 @@ sna_dri2_remove_event(WindowPtr win, struct sna_dri2_event *info)
 	assert(priv);
 	assert(priv->chain != NULL);
 
-	if (priv->chain == info) {
-		priv->chain = info->chain;
+	if (priv->chain != info) {
+		chain = priv->chain;
+		while (chain->chain != info)
+			chain = chain->chain;
+		assert(chain != info);
+		assert(info->chain != chain);
+		chain->chain = info->chain;
 		return;
 	}
 
-	chain = priv->chain;
-	while (chain->chain != info)
-		chain = chain->chain;
-	assert(chain != info);
-	assert(info->chain != chain);
-	chain->chain = info->chain;
+	priv->chain = info->chain;
+	if (priv->chain == NULL) {
+		while (!list_is_empty(&priv->cache)) {
+			struct dri_bo *c;
+
+			c = list_first_entry(&priv->cache, struct dri_bo, link);
+			list_del(&c->link);
+
+			DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
+			if (c->bo)
+				kgem_bo_destroy(&info->sna->kgem, c->bo);
+
+			free(c);
+		}
+	}
 }
 
 static void
@@ -1429,19 +1444,6 @@ sna_dri2_event_free(struct sna_dri2_event *info)
 	_sna_dri2_destroy_buffer(info->sna, info->front);
 	_sna_dri2_destroy_buffer(info->sna, info->back);
 
-	while (!list_is_empty(&info->cache)) {
-		struct dri_bo *c;
-
-		c = list_first_entry(&info->cache, struct dri_bo, link);
-		list_del(&c->link);
-
-		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
-		if (c->bo)
-			kgem_bo_destroy(&info->sna->kgem, c->bo);
-
-		free(c);
-	}
-
 	if (info->bo) {
 		DBG(("%s: releasing batch handle=%d\n", __FUNCTION__, info->bo->handle));
 		kgem_bo_destroy(&info->sna->kgem, info->bo);
@@ -1528,7 +1530,6 @@ sna_dri2_add_event(struct sna *sna,
 	if (info == NULL)
 		return NULL;
 
-	list_init(&info->cache);
 	info->sna = sna;
 	info->draw = draw;
 	info->crtc = crtc;
@@ -1612,6 +1613,21 @@ void sna_dri2_destroy_window(WindowPtr win)
 		}
 	}
 
+	while (!list_is_empty(&priv->cache)) {
+		struct dri_bo *c;
+
+		c = list_first_entry(&priv->cache, struct dri_bo, link);
+		list_del(&c->link);
+
+		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
+		if (c->bo) {
+			struct sna *sna = to_sna_from_drawable(&win->drawable);
+			kgem_bo_destroy(&sna->kgem, c->bo);
+		}
+
+		free(c);
+	}
+
 	free(priv);
 }
 
@@ -2254,8 +2270,6 @@ static void chain_swap(struct sna_dri2_event *chain)
 			__sna_dri2_copy_event(chain, 0);
 		}
 		get_private(chain->back)->bo = tmp;
-		kgem_bo_destroy(&chain->sna->kgem,
-				get_private(chain->back)->copy);
 		get_private(chain->back)->copy = NULL;
 	case SWAP:
 		break;
@@ -2472,13 +2486,10 @@ sna_dri2_immediate_blit(struct sna *sna,
 	     get_private(info->back)->bo->handle,
 	     get_private(info->back)->copy ? get_private(info->back)->copy->active_scanout : 0,
 	     get_private(info->back)->copy ? get_private(info->back)->copy->handle : 0));
-	if (get_private(info->back)->copy) {
-		get_private(info->back)->copy->active_scanout--;
-		kgem_bo_destroy(&info->sna->kgem,
-				get_private(info->back)->copy);
-	}
-	get_private(info->back)->copy = ref(get_private(info->back)->bo);
 	assert(get_private(info->back)->bo->active_scanout == 0);
+	if (get_private(info->back)->copy)
+		get_private(info->back)->copy->active_scanout--;
+	get_private(info->back)->copy = get_private(info->back)->bo;
 	get_private(info->back)->bo->active_scanout++;
 
 	if (chain->chain != info && chain->chain->type == SWAP_THROTTLE) {
@@ -2849,7 +2860,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 		if (info->type >= FLIP_COMPLETE) {
 new_back:
 			if (!xorg_can_triple_buffer())
-				sna_dri2_get_back(sna, draw, back, info);
+				sna_dri2_get_back(sna, draw, back);
 			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
 			frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE);
 			if (info->type == FLIP_ASYNC)


More information about the xorg-commit mailing list